sstrings.inc 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897
  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<0 then
  18. len:=0;
  19. if len>high(s) then
  20. len:=high(s);
  21. s[0]:=chr(len);
  22. end;
  23. {$endif FPC_HAS_SHORTSTR_SETLENGTH}
  24. {$ifndef FPC_HAS_SHORTSTR_COPY}
  25. {$define FPC_HAS_SHORTSTR_COPY}
  26. function fpc_shortstr_copy(const s : shortstring;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  27. begin
  28. if count<0 then
  29. count:=0;
  30. if index>1 then
  31. dec(index)
  32. else
  33. index:=0;
  34. if index>length(s) then
  35. count:=0
  36. else
  37. if count>length(s)-index then
  38. count:=length(s)-index;
  39. fpc_shortstr_Copy[0]:=chr(Count);
  40. fpc_shortstr_shortstr_intern_charmove(s,Index+1,fpc_shortstr_Copy,1,Count);
  41. end;
  42. {$endif FPC_HAS_SHORTSTR_COPY}
  43. {$ifndef FPC_HAS_SHORTSTR_DELETE}
  44. {$define FPC_HAS_SHORTSTR_DELETE}
  45. procedure fpc_shortstr_delete(var s : shortstring;index : SizeInt;count : SizeInt);
  46. begin
  47. if index<=0 then
  48. exit;
  49. if (Index<=Length(s)) and (Count>0) then
  50. begin
  51. if Count>length(s)-Index then
  52. Count:=length(s)-Index+1;
  53. s[0]:=Chr(length(s)-Count);
  54. if Index<=Length(s) then
  55. fpc_shortstr_shortstr_intern_charmove(s,Index+Count,s,Index,Length(s)-Index+1);
  56. end;
  57. end;
  58. {$endif FPC_HAS_SHORTSTR_DELETE}
  59. {$ifndef FPC_HAS_SHORTSTR_INSERT}
  60. {$define FPC_HAS_SHORTSTR_INSERT}
  61. procedure fpc_shortstr_insert(const source : shortstring;var s : shortstring;index : SizeInt);
  62. var
  63. cut,srclen,indexlen : SizeInt;
  64. begin
  65. if index<1 then
  66. index:=1;
  67. if index>length(s) then
  68. begin
  69. index:=length(s)+1;
  70. if index>high(s) then
  71. exit;
  72. end;
  73. indexlen:=Length(s)-Index+1;
  74. srclen:=length(Source);
  75. if sizeInt(length(source))+sizeint(length(s))>=sizeof(s) then
  76. begin
  77. cut:=sizeInt(length(source))+sizeint(length(s))-sizeof(s)+1;
  78. if cut>indexlen then
  79. begin
  80. dec(srclen,cut-indexlen);
  81. indexlen:=0;
  82. end
  83. else
  84. dec(indexlen,cut);
  85. end;
  86. fpc_shortstr_shortstr_intern_charmove(s,Index,s,Index+srclen,indexlen);
  87. fpc_shortstr_shortstr_intern_charmove(Source,1,s,Index,srclen);
  88. s[0]:=chr(index+srclen+indexlen-1);
  89. end;
  90. {$endif FPC_HAS_SHORTSTR_INSERT}
  91. {$ifndef FPC_HAS_SHORTSTR_INSERT_CHAR}
  92. {$define FPC_HAS_SHORTSTR_INSERT_CHAR}
  93. procedure fpc_shortstr_insert_char(source : AnsiChar;var s : shortstring;index : SizeInt);
  94. var
  95. indexlen : SizeInt;
  96. begin
  97. if index<1 then
  98. index:=1;
  99. if index>length(s) then
  100. begin
  101. index:=length(s)+1;
  102. if index>high(s) then
  103. exit;
  104. end;
  105. indexlen:=Length(s)-Index+1;
  106. if (sizeint(length(s))+1=sizeof(s)) and (indexlen>0) then
  107. dec(indexlen);
  108. fpc_shortstr_shortstr_intern_charmove(s,Index,s,Index+1,indexlen);
  109. s[Index]:=Source;
  110. s[0]:=chr(index+indexlen);
  111. end;
  112. {$endif FPC_HAS_SHORTSTR_INSERT_CHAR}
  113. {$ifndef FPC_HAS_SHORTSTR_POS_SHORTSTR}
  114. {$define FPC_HAS_SHORTSTR_POS_SHORTSTR}
  115. function pos(const substr : shortstring;const s : shortstring; Offset : Sizeint = 1):SizeInt;
  116. var
  117. i,MaxLen,d : SizeInt;
  118. begin
  119. Pos:=0;
  120. if (Length(SubStr)>0) and (Offset>0) and (Offset<=Length(S)) then
  121. begin
  122. MaxLen:=sizeint(Length(s))-Length(SubStr)+1;
  123. i:=Offset;
  124. while (i<=MaxLen) do
  125. begin
  126. d:=IndexByte(s[i],MaxLen-i+1,byte(substr[1]));
  127. if d<0 then
  128. exit;
  129. if (CompareByte(Substr[1],s[i+d],Length(SubStr))=0) then
  130. exit(i+d);
  131. i:=i+d+1;
  132. end;
  133. end;
  134. end;
  135. {$endif FPC_HAS_SHORTSTR_POS_SHORTSTR}
  136. {$ifndef FPC_HAS_SHORTSTR_POS_CHAR}
  137. {$define FPC_HAS_SHORTSTR_POS_CHAR}
  138. {Faster when looking for a single AnsiChar...}
  139. function pos(c:ansichar;const s:shortstring; Offset : Sizeint = 1 ):SizeInt;
  140. var
  141. idx : SizeInt;
  142. begin
  143. Pos:=0;
  144. if (Offset<1) or (Offset>Length(S)) then
  145. exit;
  146. idx:=IndexByte(s[Offset],length(s)-Offset+1,byte(c));
  147. if idx>=0 then
  148. Pos:=Offset+idx;
  149. end;
  150. {$endif FPC_HAS_SHORTSTR_POS_CHAR}
  151. function fpc_char_copy(c:ansichar;index : SizeInt;count : SizeInt): shortstring;compilerproc;
  152. begin
  153. if (index=1) and (Count>0) then
  154. fpc_char_Copy:=c
  155. else
  156. fpc_char_Copy:='';
  157. end;
  158. function pos(const substr : shortstring;c:Ansichar; Offset : Sizeint = 1): SizeInt;
  159. begin
  160. if (length(substr)=1) and (substr[1]=c) and (Offset=1) then
  161. Pos:=1
  162. else
  163. Pos:=0;
  164. end;
  165. {$if not defined(FPC_UPCASE_CHAR) or not defined(FPC_LOWERCASE_CHAR)}
  166. {$ifdef IBM_CHAR_SET}
  167. const
  168. UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
  169. LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
  170. {$endif}
  171. {$endif}
  172. {$ifndef FPC_UPCASE_CHAR}
  173. {$define FPC_UPCASE_CHAR}
  174. function upcase(c : Ansichar) : Ansichar;
  175. {$IFDEF IBM_CHAR_SET}
  176. var
  177. i : ObjpasInt;
  178. {$ENDIF}
  179. begin
  180. if (c in ['a'..'z']) then
  181. upcase:=AnsiChar(byte(c)-32)
  182. else
  183. {$IFDEF IBM_CHAR_SET}
  184. begin
  185. i:=Pos(c,LoCaseTbl);
  186. if i>0 then
  187. upcase:=UpCaseTbl[i]
  188. else
  189. upcase:=c;
  190. end;
  191. {$ELSE}
  192. upcase:=c;
  193. {$ENDIF}
  194. end;
  195. {$endif FPC_UPCASE_CHAR}
  196. {$ifndef FPC_UPCASE_SHORTSTR}
  197. {$define FPC_UPCASE_SHORTSTR}
  198. function upcase(const s : shortstring) : shortstring;
  199. var
  200. i : ObjpasInt;
  201. begin
  202. upcase[0]:=s[0];
  203. for i := 1 to length (s) do
  204. upcase[i] := upcase (s[i]);
  205. end;
  206. {$endif FPC_UPCASE_SHORTSTR}
  207. {$ifndef FPC_LOWERCASE_CHAR}
  208. {$define FPC_LOWERCASE_CHAR}
  209. function lowercase(c : AnsiChar) : AnsiChar;overload;
  210. {$IFDEF IBM_CHAR_SET}
  211. var
  212. i : ObjpasInt;
  213. {$ENDIF}
  214. begin
  215. if (c in ['A'..'Z']) then
  216. lowercase:=AnsiChar(byte(c)+32)
  217. else
  218. {$IFDEF IBM_CHAR_SET}
  219. begin
  220. i:=Pos(c,UpCaseTbl);
  221. if i>0 then
  222. lowercase:=LoCaseTbl[i]
  223. else
  224. lowercase:=c;
  225. end;
  226. {$ELSE}
  227. lowercase:=c;
  228. {$ENDIF}
  229. end;
  230. {$endif FPC_LOWERCASE_CHAR}
  231. {$ifndef FPC_LOWERCASE_SHORTSTR}
  232. {$define FPC_LOWERCASE_SHORTSTR}
  233. function lowercase(const s : shortstring) : shortstring; overload;
  234. var
  235. i : ObjpasInt;
  236. begin
  237. lowercase [0]:=s[0];
  238. for i:=1 to length(s) do
  239. lowercase[i]:=lowercase (s[i]);
  240. end;
  241. {$endif FPC_LOWERCASE_SHORTSTR}
  242. const
  243. HexTbl : array[0..15] of AnsiChar='0123456789ABCDEF';
  244. function hexstr(val : longint;cnt : byte) : shortstring;
  245. var
  246. i : ObjpasInt;
  247. begin
  248. hexstr[0]:=AnsiChar(cnt);
  249. for i:=cnt downto 1 do
  250. begin
  251. hexstr[i]:=hextbl[val and $f];
  252. val:=val shr 4;
  253. end;
  254. end;
  255. function octstr(val : longint;cnt : byte) : shortstring;
  256. var
  257. i : ObjpasInt;
  258. begin
  259. octstr[0]:=AnsiChar(cnt);
  260. for i:=cnt downto 1 do
  261. begin
  262. octstr[i]:=hextbl[val and 7];
  263. val:=val shr 3;
  264. end;
  265. end;
  266. function binstr(val : longint;cnt : byte) : shortstring;
  267. var
  268. i : ObjpasInt;
  269. begin
  270. binstr[0]:=AnsiChar(cnt);
  271. for i:=cnt downto 1 do
  272. begin
  273. binstr[i]:=AnsiChar(48+val and 1);
  274. val:=val shr 1;
  275. end;
  276. end;
  277. function hexstr(val : int64;cnt : byte) : shortstring;
  278. var
  279. i : ObjpasInt;
  280. begin
  281. hexstr[0]:=AnsiChar(cnt);
  282. for i:=cnt downto 1 do
  283. begin
  284. hexstr[i]:=hextbl[val and $f];
  285. val:=val shr 4;
  286. end;
  287. end;
  288. function octstr(val : int64;cnt : byte) : shortstring;
  289. var
  290. i : ObjpasInt;
  291. begin
  292. octstr[0]:=AnsiChar(cnt);
  293. for i:=cnt downto 1 do
  294. begin
  295. octstr[i]:=hextbl[val and 7];
  296. val:=val shr 3;
  297. end;
  298. end;
  299. function binstr(val : int64;cnt : byte) : shortstring;
  300. var
  301. i : ObjpasInt;
  302. begin
  303. binstr[0]:=AnsiChar(cnt);
  304. for i:=cnt downto 1 do
  305. begin
  306. binstr[i]:=AnsiChar(48+val and 1);
  307. val:=val shr 1;
  308. end;
  309. end;
  310. {$ifndef FPC_HAS_QWORD_HEX_SHORTSTR}
  311. {$define FPC_HAS_QWORD_HEX_SHORTSTR}
  312. Function hexStr(Val:qword;cnt:byte):shortstring;
  313. begin
  314. hexStr:=hexStr(int64(Val),cnt);
  315. end;
  316. {$endif FPC_HAS_QWORD_HEX_SHORTSTR}
  317. {$ifndef FPC_HAS_QWORD_OCT_SHORTSTR}
  318. {$define FPC_HAS_QWORD_OCT_SHORTSTR}
  319. Function OctStr(Val:qword;cnt:byte):shortstring;
  320. begin
  321. OctStr:=OctStr(int64(Val),cnt);
  322. end;
  323. {$endif FPC_HAS_QWORD_OCT_SHORTSTR}
  324. {$ifndef FPC_HAS_QWORD_BIN_SHORTSTR}
  325. {$define FPC_HAS_QWORD_BIN_SHORTSTR}
  326. Function binStr(Val:qword;cnt:byte):shortstring;
  327. begin
  328. binStr:=binStr(int64(Val),cnt);
  329. end;
  330. {$endif FPC_HAS_QWORD_BIN_SHORTSTR}
  331. {$ifndef FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  332. {$define FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  333. function hexstr(val : pointer) : shortstring;
  334. var
  335. i : ObjpasInt;
  336. v : ptruint;
  337. begin
  338. v:=ptruint(val);
  339. hexstr[0]:=chr(sizeof(pointer)*2);
  340. for i:=sizeof(pointer)*2 downto 1 do
  341. begin
  342. hexstr[i]:=hextbl[v and $f];
  343. v:=v shr 4;
  344. end;
  345. end;
  346. {$endif FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  347. {$ifndef FPC_HAS_SPACE_SHORTSTR}
  348. {$define FPC_HAS_SPACE_SHORTSTR}
  349. function space (b : byte): shortstring;
  350. begin
  351. space[0] := chr(b);
  352. FillChar (Space[1],b,' ');
  353. end;
  354. {$endif FPC_HAS_SPACE_SHORTSTR}
  355. {*****************************************************************************
  356. Str() Helpers
  357. *****************************************************************************}
  358. procedure fpc_shortstr_SInt(v : valSInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_SINT']; compilerproc;
  359. begin
  360. int_str(v,s);
  361. if length(s)<len then
  362. s:=space(len-length(s))+s;
  363. end;
  364. procedure fpc_shortstr_UInt(v : valUInt;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_UINT']; compilerproc;
  365. begin
  366. int_str_unsigned(v,s);
  367. if length(s)<len then
  368. s:=space(len-length(s))+s;
  369. end;
  370. {$ifndef CPU64}
  371. procedure fpc_shortstr_qword(v : qword;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_QWORD']; compilerproc;
  372. begin
  373. int_str_unsigned(v,s);
  374. if length(s)<len then
  375. s:=space(len-length(s))+s;
  376. end;
  377. procedure fpc_shortstr_int64(v : int64;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_INT64']; compilerproc;
  378. begin
  379. int_str(v,s);
  380. if length(s)<len then
  381. s:=space(len-length(s))+s;
  382. end;
  383. {$endif CPU64}
  384. {$if defined(CPU16) or defined(CPU8)}
  385. procedure fpc_shortstr_longword(v : longword;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_LONGWORD']; compilerproc;
  386. begin
  387. int_str_unsigned(v,s);
  388. if length(s)<len then
  389. s:=space(len-length(s))+s;
  390. end;
  391. procedure fpc_shortstr_longint(v : longint;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_LONGINT']; compilerproc;
  392. begin
  393. int_str(v,s);
  394. if length(s)<len then
  395. s:=space(len-length(s))+s;
  396. end;
  397. procedure fpc_shortstr_word(v : word;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_WORD']; compilerproc;
  398. begin
  399. int_str_unsigned(v,s);
  400. if length(s)<len then
  401. s:=space(len-length(s))+s;
  402. end;
  403. procedure fpc_shortstr_smallint(v : smallint;len : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_SMALLINT']; compilerproc;
  404. begin
  405. int_str(v,s);
  406. if length(s)<len then
  407. s:=space(len-length(s))+s;
  408. end;
  409. {$endif CPU16 or CPU8}
  410. { fpc_shortstr_sInt must appear before this file is included, because }
  411. { it's used inside real2str.inc and otherwise the searching via the }
  412. { compilerproc name will fail (JM) }
  413. {$ifndef FPUNONE}
  414. {$I flt_conv.inc}
  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. {$ifndef FPC_HAS_FEATURE_RTTI}
  425. begin
  426. int_str(ordinal,s);
  427. if length(s)<len then
  428. s:=space(len-length(s))+s;
  429. end;
  430. {$else with RTTI feature}
  431. { The following contains the TTypeInfo/TTypeData records from typinfo.pp
  432. specialized for the tkEnumeration case (and stripped of unused things). }
  433. type
  434. PPstring=^Pstring;
  435. Penum_typeinfo=^Tenum_typeinfo;
  436. Tenum_typeinfo={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  437. kind:TTypeKind; { always tkEnumeration }
  438. num_chars:byte;
  439. chars:array[0..0] of AnsiChar; { variable length with size of num_chars }
  440. end;
  441. {$push}
  442. {$packrecords c}
  443. Penum_typedata=^Tenum_typedata;
  444. Tenum_typedata={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  445. {$if declared(TRttiDataCommon)}
  446. Common: TRttiDataCommon;
  447. {$endif}
  448. case TTypeKind of
  449. tkInt64,tkQWord,tkInteger,tkChar,tkEnumeration,tkBool,tkWChar: (
  450. OrdType : Byte;
  451. case TTypeKind of
  452. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar: (
  453. MinValue,MaxValue : Longint;
  454. case TTypeKind of
  455. tkEnumeration: (
  456. BaseTypeRef : pointer
  457. );
  458. {tkBool with OrdType=otSQWord }
  459. tkInt64:
  460. (MinInt64Value, MaxInt64Value: Int64);
  461. {tkBool with OrdType=otUQWord }
  462. tkQWord:
  463. (MinQWordValue, MaxQWordValue: QWord);
  464. );
  465. );
  466. { more data here, but not needed }
  467. end;
  468. { Pascal data types for the ordinal enum value to string table. It consists of a header
  469. that indicates what type of data the table stores, either a direct lookup table (when
  470. o = lookup) or a set of ordered (ordinal value, string) tuples (when o = search). }
  471. { A single entry in the set of ordered tuples }
  472. Psearch_data=^Tsearch_data;
  473. Tsearch_data={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  474. value:longint;
  475. name:Pstring;
  476. end;
  477. Penum_ord_to_string=^Tenum_ord_to_string;
  478. Tenum_ord_to_string={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  479. o:(lookup,search);
  480. case integer of
  481. 0: (lookup_data:array[0..0] of Pstring);
  482. 1: (num_entries:longint;
  483. search_data:array[0..0] of Tsearch_data);
  484. end;
  485. {$pop}
  486. var
  487. enum_o2s : Penum_ord_to_string;
  488. header:Penum_typeinfo;
  489. body:Penum_typedata;
  490. res:Pshortstring;
  491. sorted_data:Psearch_data;
  492. spaces,i,m,h,l:longint;
  493. begin
  494. { set default return value }
  495. fpc_shortstr_enum_intern:=107;
  496. enum_o2s:=Penum_ord_to_string(ord2strindex);
  497. { depending on the type of table in ord2strindex retrieve the data }
  498. if (enum_o2s^.o=lookup) then
  499. begin
  500. { direct lookup table }
  501. header:=Penum_typeinfo(typinfo);
  502. { calculate address of enum rtti body: add the actual size of the
  503. enum_rtti_header, and then align. Use an alignment of 1 (which
  504. does nothing) in case FPC_REQUIRES_PROPER_ALIGNMENT is not set
  505. to avoid the need for an if in this situation }
  506. body:=Penum_typedata(aligntoqword(pointer(header) + 2 * sizeof(byte) { kind, num_chars } + header^.num_chars));
  507. with body^ do
  508. begin
  509. { Bounds check for the ordinal value for this enum }
  510. if (ordinal<minvalue) or (ordinal>maxvalue) then
  511. exit;
  512. { make the ordinal index for lookup zero-based }
  513. dec(ordinal,minvalue);
  514. end;
  515. { temporarily disable range checking because of the access to the array[0..0]
  516. member of Tenum_ord_to_string_lookup }
  517. {$push}{$R-}
  518. res:=enum_o2s^.lookup_data[ordinal];
  519. {$pop}
  520. if (not assigned(res)) then
  521. exit;
  522. s:=res^;
  523. end
  524. else
  525. begin
  526. { The compiler did generate a sorted array of (ordvalue,Pstring) tuples }
  527. sorted_data:=@enum_o2s^.search_data;
  528. { Use a binary search to get the string }
  529. l:=0;
  530. { temporarily disable range checking because of the access to the array[0..0]
  531. member of Tenum_ord_to_string_search }
  532. {$push}{$R-}
  533. h:=enum_o2s^.num_entries-1;
  534. repeat
  535. m:=(l+h) div 2;
  536. if ordinal>sorted_data[m].value then
  537. l:=m+1
  538. else if ordinal<sorted_data[m].value then
  539. h:=m-1
  540. else
  541. break;
  542. if l>h then
  543. exit; { Ordinal value not found? Exit }
  544. until false;
  545. {$pop}
  546. s:=sorted_data[m].name^;
  547. end;
  548. { Pad the string with spaces if necessary }
  549. if (len>length(s)) then
  550. begin
  551. spaces:=len-length(s);
  552. for i:=1 to spaces do
  553. s[length(s)+i]:=' ';
  554. inc(byte(s[0]),spaces);
  555. end;
  556. fpc_shortstr_enum_intern:=0;
  557. end;
  558. {$endif with RTTI feature}
  559. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);[public,alias:'FPC_SHORTSTR_ENUM'];compilerproc;
  560. var
  561. res: longint;
  562. begin
  563. res:=fpc_shortstr_enum_intern(ordinal,len,typinfo,ord2strindex,s);
  564. if (res<>0) then
  565. runerror(107);
  566. end;
  567. { also define alias for internal use in the system unit }
  568. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);external name 'FPC_SHORTSTR_ENUM';
  569. {$endif FPC_SHORTSTR_ENUM_INTERN}
  570. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);[public,alias:'FPC_SHORTSTR_BOOL'];compilerproc;
  571. begin
  572. if b then
  573. s:='TRUE'
  574. else
  575. s:='FALSE';
  576. if length(s)<len then
  577. s:=space(len-length(s))+s;
  578. end;
  579. { also define alias for internal use in the system unit }
  580. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);external {$ifndef cpujvm}name 'FPC_SHORTSTR_BOOL'{$endif};
  581. procedure fpc_shortstr_currency({$ifdef cpujvm}constref{$endif} c : currency; len,f : SizeInt; out s : shortstring);[public,alias:'FPC_SHORTSTR_CURRENCY']; compilerproc;
  582. const
  583. MinLen = 8; { Minimal string length in scientific format }
  584. var
  585. buf : array[1..19] of AnsiChar;
  586. i,j,k,reslen,tlen,sign,r,point : ObjpasInt;
  587. ic : qword;
  588. begin
  589. fillchar(buf,length(buf),'0');
  590. { default value for length is -32767 }
  591. if len=-32767 then
  592. len:=25;
  593. if PInt64(@c)^ >= 0 then
  594. begin
  595. ic:=QWord(PInt64(@c)^);
  596. sign:=0;
  597. end
  598. else
  599. begin
  600. sign:=1;
  601. ic:=QWord(-PInt64(@c)^);
  602. end;
  603. { converting to integer string }
  604. tlen:=0;
  605. repeat
  606. Inc(tlen);
  607. buf[tlen]:=Chr(ic mod 10 + $30);
  608. ic:=ic div 10;
  609. until ic = 0;
  610. { calculating:
  611. reslen - length of result string,
  612. r - rounding or appending zeroes,
  613. point - place of decimal point }
  614. reslen:=tlen;
  615. if f <> 0 then
  616. Inc(reslen); { adding decimal point length }
  617. if f < 0 then
  618. begin
  619. { scientific format }
  620. Inc(reslen,5); { adding length of sign and exponent }
  621. if len < MinLen then
  622. len:=MinLen;
  623. r:=reslen-len;
  624. if reslen < len then
  625. reslen:=len;
  626. if r > 0 then
  627. begin
  628. reslen:=len;
  629. point:=tlen - r;
  630. end
  631. else
  632. point:=tlen;
  633. end
  634. else
  635. begin
  636. { fixed format }
  637. Inc(reslen, sign);
  638. { prepending fractional part with zeroes }
  639. while tlen < 5 do
  640. begin
  641. Inc(reslen);
  642. Inc(tlen);
  643. buf[tlen]:='0';
  644. end;
  645. { Currency have 4 digits in fractional part }
  646. r:=4 - f;
  647. point:=f;
  648. if point <> 0 then
  649. begin
  650. if point > 4 then
  651. point:=4;
  652. Inc(point);
  653. end;
  654. Dec(reslen,r);
  655. end;
  656. { rounding string if r > 0 }
  657. if r > 0 then
  658. begin
  659. k := 0;
  660. i := r+2;
  661. if i > tlen then
  662. i := tlen+1;
  663. if buf[i-2] >= '5' then
  664. begin
  665. if buf[i-1] < '9' then
  666. buf[i-1] := chr(ord(buf[i-1])+1)
  667. else
  668. begin
  669. buf[i-1] := '0';
  670. k := 1;
  671. end;
  672. end;
  673. If (k=1) and (buf[i-1]='0') then
  674. begin
  675. { 1.9996 rounded to two decimal digits after the decimal separator must result in
  676. 2.00, i.e. the rounding is propagated
  677. }
  678. while buf[i]='9' do
  679. begin
  680. buf[i]:='0';
  681. inc(i);
  682. end;
  683. buf[i]:=chr(Ord(buf[i])+1);
  684. { did we add another digit? This happens when rounding
  685. e.g. 99.9996 to two decimal digits after the decimal separator which should result in
  686. 100.00
  687. }
  688. if i>tlen then
  689. begin
  690. inc(reslen);
  691. inc(tlen);
  692. end;
  693. end;
  694. end;
  695. { preparing result string }
  696. if reslen<len then
  697. reslen:=len;
  698. if reslen>High(s) then
  699. begin
  700. if r < 0 then
  701. Inc(r, reslen - High(s));
  702. reslen:=High(s);
  703. end;
  704. SetLength(s,reslen);
  705. j:=reslen;
  706. if f<0 then
  707. begin
  708. { writing power of 10 part }
  709. if PInt64(@c)^ = 0 then
  710. k:=0
  711. else
  712. k:=tlen-5;
  713. if k >= 0 then
  714. s[j-2]:='+'
  715. else
  716. begin
  717. s[j-2]:='-';
  718. k:=-k;
  719. end;
  720. s[j]:=Chr(k mod 10 + $30);
  721. Dec(j);
  722. s[j]:=Chr(k div 10 + $30);
  723. Dec(j,2);
  724. s[j]:='E';
  725. Dec(j);
  726. end;
  727. { writing extra zeroes if r < 0 }
  728. while r < 0 do
  729. begin
  730. s[j]:='0';
  731. Dec(j);
  732. Inc(r);
  733. end;
  734. { writing digits and decimal point }
  735. for i:=r + 1 to tlen do
  736. begin
  737. Dec(point);
  738. if point = 0 then
  739. begin
  740. s[j]:='.';
  741. Dec(j);
  742. end;
  743. s[j]:=buf[i];
  744. Dec(j);
  745. end;
  746. { writing sign }
  747. if sign = 1 then
  748. begin
  749. s[j]:='-';
  750. Dec(j);
  751. end;
  752. { writing spaces }
  753. while j > 0 do
  754. begin
  755. s[j]:=' ';
  756. Dec(j);
  757. end;
  758. end;
  759. {
  760. Array Of AnsiChar Str() helpers
  761. }
  762. procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of AnsiChar);compilerproc;
  763. var
  764. ss : shortstring;
  765. maxlen : SizeInt;
  766. begin
  767. int_str(v,ss);
  768. if length(ss)<len then
  769. ss:=space(len-length(ss))+ss;
  770. if length(ss)<high(a)+1 then
  771. maxlen:=length(ss)
  772. else
  773. maxlen:=high(a)+1;
  774. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  775. end;
  776. procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of AnsiChar);compilerproc;
  777. var
  778. ss : shortstring;
  779. maxlen : SizeInt;
  780. begin
  781. int_str_unsigned(v,ss);
  782. if length(ss)<len then
  783. ss:=space(len-length(ss))+ss;
  784. if length(ss)<high(a)+1 then
  785. maxlen:=length(ss)
  786. else
  787. maxlen:=high(a)+1;
  788. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  789. end;
  790. {$ifndef CPU64}
  791. procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of AnsiChar);compilerproc;
  792. {$ifdef EXCLUDE_COMPLEX_PROCS}
  793. begin
  794. runerror(219);
  795. end;
  796. {$else EXCLUDE_COMPLEX_PROCS}
  797. var
  798. ss : shortstring;
  799. maxlen : SizeInt;
  800. begin
  801. int_str_unsigned(v,ss);
  802. if length(ss)<len then
  803. ss:=space(len-length(ss))+ss;
  804. if length(ss)<high(a)+1 then
  805. maxlen:=length(ss)
  806. else
  807. maxlen:=high(a)+1;
  808. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  809. end;
  810. {$endif EXCLUDE_COMPLEX_PROCS}
  811. procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of AnsiChar);compilerproc;
  812. {$ifdef EXCLUDE_COMPLEX_PROCS}
  813. begin
  814. runerror(219);
  815. end;
  816. {$else EXCLUDE_COMPLEX_PROCS}
  817. var
  818. ss : shortstring;
  819. maxlen : SizeInt;
  820. begin
  821. int_str(v,ss);
  822. if length(ss)<len then
  823. ss:=space(len-length(ss))+ss;
  824. if length(ss)<high(a)+1 then
  825. maxlen:=length(ss)
  826. else
  827. maxlen:=high(a)+1;
  828. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  829. end;
  830. {$endif EXCLUDE_COMPLEX_PROCS}
  831. {$endif CPU64}
  832. {$if defined(CPU16) or defined(CPU8)}
  833. procedure fpc_chararray_longword(v : longword;len : SizeInt;out a : array of AnsiChar);compilerproc;
  834. var
  835. ss : shortstring;
  836. maxlen : SizeInt;
  837. begin
  838. int_str_unsigned(v,ss);
  839. if length(ss)<len then
  840. ss:=space(len-length(ss))+ss;
  841. if length(ss)<high(a)+1 then
  842. maxlen:=length(ss)
  843. else
  844. maxlen:=high(a)+1;
  845. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  846. end;
  847. procedure fpc_chararray_longint(v : longint;len : SizeInt;out a : array of AnsiChar);compilerproc;
  848. var
  849. ss : shortstring;
  850. maxlen : SizeInt;
  851. begin
  852. int_str(v,ss);
  853. if length(ss)<len then
  854. ss:=space(len-length(ss))+ss;
  855. if length(ss)<high(a)+1 then
  856. maxlen:=length(ss)
  857. else
  858. maxlen:=high(a)+1;
  859. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  860. end;
  861. procedure fpc_chararray_word(v : word;len : SizeInt;out a : array of AnsiChar);compilerproc;
  862. var
  863. ss : shortstring;
  864. maxlen : SizeInt;
  865. begin
  866. int_str_unsigned(v,ss);
  867. if length(ss)<len then
  868. ss:=space(len-length(ss))+ss;
  869. if length(ss)<high(a)+1 then
  870. maxlen:=length(ss)
  871. else
  872. maxlen:=high(a)+1;
  873. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  874. end;
  875. procedure fpc_chararray_smallint(v : smallint;len : SizeInt;out a : array of AnsiChar);compilerproc;
  876. var
  877. ss : shortstring;
  878. maxlen : SizeInt;
  879. begin
  880. int_str(v,ss);
  881. if length(ss)<len then
  882. ss:=space(len-length(ss))+ss;
  883. if length(ss)<high(a)+1 then
  884. maxlen:=length(ss)
  885. else
  886. maxlen:=high(a)+1;
  887. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  888. end;
  889. {$endif CPU16 or CPU8}
  890. {$ifndef FPUNONE}
  891. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of AnsiChar);compilerproc;
  892. var
  893. ss : shortstring;
  894. maxlen : SizeInt;
  895. begin
  896. str_real(len,fr,d,treal_type(rt),ss);
  897. if length(ss)<high(a)+1 then
  898. maxlen:=length(ss)
  899. else
  900. maxlen:=high(a)+1;
  901. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  902. end;
  903. {$endif}
  904. {$ifndef FPC_STR_ENUM_INTERN}
  905. { currently, the avr code generator fails on this procedure, so we disable it,
  906. this is not a good solution but fixing compilation of this procedure for
  907. avr is hard, requires significant changes to the register allocator to take
  908. care of different register classes }
  909. procedure fpc_chararray_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out a : array of AnsiChar);compilerproc;
  910. var
  911. ss : shortstring;
  912. maxlen : SizeInt;
  913. begin
  914. {$ifdef EXCLUDE_COMPLEX_PROCS}
  915. runerror(219);
  916. {$else EXCLUDE_COMPLEX_PROCS}
  917. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  918. if length(ss)<high(a)+1 then
  919. maxlen:=length(ss)
  920. else
  921. maxlen:=high(a)+1;
  922. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  923. {$endif EXCLUDE_COMPLEX_PROCS}
  924. end;
  925. {$endif not FPC_STR_ENUM_INTERN}
  926. procedure fpc_chararray_bool(b : boolean;len:sizeint;out a : array of AnsiChar);compilerproc;
  927. var
  928. ss : shortstring;
  929. maxlen : SizeInt;
  930. begin
  931. fpc_shortstr_bool(b,len,ss);
  932. if length(ss)<high(a)+1 then
  933. maxlen:=length(ss)
  934. else
  935. maxlen:=high(a)+1;
  936. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  937. end;
  938. {$ifndef FPC_HAS_CHARARRAY_CURRENCY}
  939. {$define FPC_HAS_CHARARRAY_CURRENCY}
  940. procedure fpc_chararray_Currency(c : Currency;len,fr : SizeInt;out a : array of AnsiChar);compilerproc;
  941. {$ifdef EXCLUDE_COMPLEX_PROCS}
  942. begin
  943. runerror(217);
  944. end;
  945. {$else EXCLUDE_COMPLEX_PROCS}
  946. var
  947. ss : shortstring;
  948. maxlen : SizeInt;
  949. begin
  950. str(c:len:fr,ss);
  951. if length(ss)<high(a)+1 then
  952. maxlen:=length(ss)
  953. else
  954. maxlen:=high(a)+1;
  955. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  956. end;
  957. {$endif EXCLUDE_COMPLEX_PROCS}
  958. {$endif FPC_HAS_CHARARRAY_CURRENCY}
  959. {*****************************************************************************
  960. Val() Functions
  961. *****************************************************************************}
  962. type
  963. ValCommon=record
  964. negative:boolean;
  965. base,baseIndex:byte; { baseIndex is flattened base for lookups: 0 — base 10, 1 — base 16, 2 — base 2, 3 — base 8. }
  966. minusPos:SizeInt;
  967. end;
  968. Function InitVal(const s:shortstring;out vc:ValCommon):ValSInt;
  969. var
  970. ns : SizeInt;
  971. begin
  972. result:=1;
  973. vc.negative:=false;
  974. vc.base:=10;
  975. vc.baseIndex:=0;
  976. ns:=length(s);
  977. {Skip Spaces and Tab}
  978. while (result<=ns) and (s[result] in [' ',#9]) do
  979. inc(result);
  980. {Sign}
  981. if result<=ns then
  982. case s[result] of
  983. '-' : begin
  984. vc.negative:=true;
  985. vc.minusPos:=result;
  986. inc(result);
  987. end;
  988. '+' : inc(result);
  989. end;
  990. {Base}
  991. if result<=ns then
  992. case s[result] of
  993. '$',
  994. 'X',
  995. 'x' : begin
  996. vc.base:=16;
  997. vc.baseIndex:=1;
  998. inc(result);
  999. end;
  1000. '%' : begin
  1001. vc.base:=2;
  1002. vc.baseIndex:=2;
  1003. inc(result);
  1004. end;
  1005. '&' : begin
  1006. vc.base:=8;
  1007. vc.baseIndex:=3;
  1008. inc(result);
  1009. end;
  1010. '0' : if (result<ns) and (s[result+1] in ['x', 'X']) then
  1011. begin
  1012. vc.base:=16;
  1013. vc.baseIndex:=1;
  1014. inc(result, 2);
  1015. end;
  1016. end;
  1017. { strip leading zeros }
  1018. while (result<ns) and (s[result]='0') and (s[result+1]<>#0) do
  1019. inc(result);
  1020. end;
  1021. const
  1022. ValData: record
  1023. ValueArray: array[0..ord('f')-ord('0')] of byte;
  1024. MaxDigits: array[0 .. 2 { unsigned / signed positive / signed negative }, 0 .. 3 { base index }, 0 .. 3 { Bsr(DestSize) }] of byte;
  1025. end =
  1026. (
  1027. ValueArray:
  1028. (
  1029. 0,1,2,3,4,5,6,7,8,9,$FF,$FF,$FF,$FF,$FF,$FF,$FF,10,11,12,13,14,15,
  1030. $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,
  1031. 10,11,12,13,14,15
  1032. );
  1033. { If VAL input has exactly this many digits (without leading zeros), then it may overflow.
  1034. If it has more digits, it definitely overflows.
  1035. If it has less, it definitely doesn’t overflow. }
  1036. MaxDigits:
  1037. (
  1038. ( { unsigned }
  1039. (3, 5, 10, 20), { base 10: 255 / 65535 / 4_294_967_295 / 18_446_744_073_709_551_615 }
  1040. (2, 4, 8, 16), { base 16: $FF / $FFFF / $FFFF_FFFF / $FFFF_FFFF_FFFF_FFFF }
  1041. (8, 16, 32, 64), { base 2: %1111_1111 / %1111_1111_1111_1111 / %1111_1111_1111_1111_1111_1111_1111_1111 / %1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111 }
  1042. (3, 6, 11, 22) { base 8: &377 / &17_7777 / &377_7777_7777 / &17_7777_7777_7777_7777_7777 }
  1043. ),
  1044. ( { signed positive }
  1045. (3, 5, 10, 19), { base 10: 127 / 32767 / 2_147_483_647 / 9_223_372_036_854_775_807 }
  1046. (2, 4, 8, 16), { base 16: $7F / $7FFF / $7FFF_FFFF / $7FFF_FFFF_FFFF_FFFF }
  1047. (7, 15, 31, 63), { base 2: %111_1111 / %111_1111_1111_1111 / %111_1111_1111_1111_1111_1111_1111_1111 / %111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111 }
  1048. (3, 5, 11, 21) { base 8: &177 / &7_7777 / &177_7777_7777 / &7_7777_7777_7777_7777_7777 }
  1049. ),
  1050. ( { signed negative }
  1051. (3, 5, 10, 19), { base 10: 128 / 32768 / 2_147_483_648 / 9_223_372_036_854_775_808 }
  1052. (2, 4, 8, 16), { base 16: $80 / $8000 / $8000_0000 / $8000_0000_0000_0000 }
  1053. (8, 16, 32, 64), { base 2: %1000_0000 / %1000_0000_0000_0000 / %1000_0000_0000_0000_0000_0000_0000_0000 / %1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000 }
  1054. (3, 6, 11, 22) { base 8: &200 / &10_0000 / &200_0000_0000 / &10_0000_0000_0000_0000_0000 }
  1055. )
  1056. )
  1057. );
  1058. type
  1059. ValNonZeroBase = 1 .. ord(High(ValCommon.base));
  1060. ValNonZeroDestSize = 1 .. ord(High(uint32));
  1061. Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
  1062. var
  1063. sp,ns : SizeInt;
  1064. u : SizeUInt;
  1065. digitsLeft,sh : ALUSint;
  1066. temp, prev, lim: ValUInt;
  1067. vc: ValCommon;
  1068. begin
  1069. fpc_Val_SInt_ShortStr:=0;
  1070. sp:=InitVal(s,vc);
  1071. ns:=length(s);
  1072. if (sp>ns) or (s[sp]=#0) then
  1073. begin
  1074. Code:=sp;
  1075. exit;
  1076. end;
  1077. digitsLeft:=ValData.MaxDigits[ord((vc.base=10) or vc.negative)+ord(vc.negative), vc.baseIndex, BsrDWord(ValNonZeroDestSize(DestSize))];
  1078. Temp:=0;
  1079. repeat
  1080. u:=SizeUint(ord(s[sp])-ord('0'));
  1081. if u>=length(ValData.ValueArray) then
  1082. break;
  1083. u:=ValData.ValueArray[u];
  1084. If u>=vc.base then
  1085. break;
  1086. dec(digitsLeft);
  1087. if digitsLeft<0 then
  1088. break;
  1089. prev:=Temp;
  1090. Temp:=Temp*ValUInt(vc.base)+u;
  1091. inc(sp);
  1092. until sp>ns;
  1093. if digitsLeft<=0 then { Maybe an overflow. If so, step 1 digit back. }
  1094. begin
  1095. if sp<=ns then { If the loop was stopped not by sp>ns check... }
  1096. u:=ValData.ValueArray[ord(s[sp-1])-ord('0')]; { Then recover previous u. }
  1097. lim:=High(lim) shr (bitsizeof(lim)-8*DestSize);
  1098. if (vc.base=10) or vc.negative then
  1099. lim:=lim shr 1+Ord(vc.negative); { Convert to signed limit. }
  1100. if prev>ValUInt(lim-u) div ValNonZeroBase(vc.base) then
  1101. dec(sp); { Overflow. Step 1 digit back. }
  1102. end;
  1103. if (sp<=ns) and (s[sp]<>#0) then
  1104. begin
  1105. Code:=sp;
  1106. exit;
  1107. end;
  1108. Code:=0;
  1109. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  1110. If vc.Negative Then
  1111. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  1112. If Not(vc.Negative) and (vc.base<>10) and (DestSize<sizeof(fpc_Val_SInt_ShortStr)) Then
  1113. begin
  1114. {sign extend the result to allow proper range checking}
  1115. sh:=bitsizeof(fpc_Val_SInt_ShortStr)-8*DestSize;
  1116. fpc_Val_SInt_ShortStr:=
  1117. {$if sizeof(ValSint)=sizeof(int64)} SarInt64
  1118. {$elseif sizeof(ValSint)=sizeof(int32)} SarLongint
  1119. {$elseif sizeof(ValSint)=sizeof(int16)} SarSmallint
  1120. {$else} {$error unknown ValSint size}
  1121. {$endif} (fpc_Val_SInt_ShortStr shl sh, sh);
  1122. End;
  1123. end;
  1124. {$ifndef FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1125. {$define FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1126. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  1127. { we have to pass the DestSize parameter on (JM) }
  1128. Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  1129. {$endif FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1130. Function fpc_Val_UInt_Shortstr({$ifndef VER3_2}DestSize: SizeInt;{$endif VER3_2} Const S: ShortString; out Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; compilerproc;
  1131. var
  1132. sp,ns : SizeInt;
  1133. u : SizeUInt;
  1134. digitsLeft : ALUSint;
  1135. prev: ValUInt;
  1136. vc: ValCommon;
  1137. begin
  1138. fpc_Val_UInt_Shortstr:=0;
  1139. sp:=InitVal(s,vc);
  1140. ns:=length(s);
  1141. If vc.negative or (sp>ns) or (s[sp]=#0) Then
  1142. begin
  1143. if vc.negative then sp:=vc.minusPos;
  1144. Code:=sp;
  1145. Exit;
  1146. end;
  1147. digitsLeft:=ValData.MaxDigits[0, vc.baseIndex, BsrDWord(ValNonZeroDestSize({$ifndef VER3_2}DestSize{$else}sizeof(fpc_Val_UInt_Shortstr){$endif}))];
  1148. repeat
  1149. u:=SizeUint(ord(s[sp])-ord('0'));
  1150. if u>=length(ValData.ValueArray) then
  1151. break;
  1152. u:=ValData.ValueArray[u];
  1153. If u>=vc.base then
  1154. break;
  1155. dec(digitsLeft);
  1156. if digitsLeft<0 then
  1157. break;
  1158. prev:=fpc_Val_UInt_Shortstr;
  1159. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(vc.base)+u;
  1160. inc(sp);
  1161. until sp>ns;
  1162. if digitsLeft<=0 then { Maybe an overflow. If so, step 1 digit back. }
  1163. begin
  1164. if sp<=ns then { If the loop was stopped not by sp>ns check... }
  1165. u:=ValData.ValueArray[ord(s[sp-1])-ord('0')]; { Then recover previous u. }
  1166. if prev>ValUInt(High(result) {$ifndef VER3_2} shr (bitsizeof(result)-8*DestSize) {$endif}-u) div ValNonZeroBase(vc.base) then
  1167. dec(sp);
  1168. end;
  1169. code:=0;
  1170. if (sp<=ns) and (s[sp]<>#0) then
  1171. begin
  1172. Code:=sp;
  1173. fpc_Val_UInt_Shortstr:=0;
  1174. end;
  1175. end;
  1176. {$ifndef CPU64}
  1177. Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
  1178. var u : sizeuint;
  1179. sp,ns : sizeint;
  1180. digitsLeft : ALUSint;
  1181. temp, prev, lim : qword;
  1182. vc : ValCommon;
  1183. begin
  1184. {$ifdef EXCLUDE_COMPLEX_PROCS}
  1185. runerror(219);
  1186. {$else EXCLUDE_COMPLEX_PROCS}
  1187. fpc_val_int64_shortstr := 0;
  1188. sp:=InitVal(s,vc);
  1189. ns:=length(s);
  1190. if (sp>ns) or (s[sp]=#0) then
  1191. begin
  1192. Code:=sp;
  1193. exit;
  1194. end;
  1195. digitsLeft:=ValData.MaxDigits[ord((vc.base=10) or vc.negative)+ord(vc.negative), vc.baseIndex, 3];
  1196. Temp:=0;
  1197. repeat
  1198. u:=SizeUint(ord(s[sp])-ord('0'));
  1199. if u>=length(ValData.ValueArray) then
  1200. break;
  1201. u:=ValData.ValueArray[u];
  1202. If u>=vc.base then
  1203. break;
  1204. dec(digitsLeft);
  1205. if digitsLeft<0 then
  1206. break;
  1207. prev:=Temp;
  1208. Temp:=Temp*vc.base+u;
  1209. inc(sp);
  1210. until sp>ns;
  1211. if digitsLeft<=0 then { Maybe an overflow. If so, step 1 digit back. }
  1212. begin
  1213. if sp<=ns then { If the loop was stopped not by sp>ns check... }
  1214. u:=ValData.ValueArray[ord(s[sp-1])-ord('0')]; { Then recover previous u. }
  1215. lim:=High(lim);
  1216. if (vc.base=10) or vc.negative then
  1217. begin
  1218. lim:=uint64(High(int64));
  1219. if vc.negative then { lim:=uint64(High(int64))+ord(vc.negative) triggers #41148. }
  1220. lim:=uint64(Low(int64));
  1221. end;
  1222. if prev>uint64(lim-u) div ValNonZeroBase(vc.base) then
  1223. dec(sp); { Overflow. Step 1 digit back. }
  1224. end;
  1225. if (sp<=ns) and (s[sp]<>#0) then
  1226. begin
  1227. Code:=sp;
  1228. exit;
  1229. end;
  1230. code:=0;
  1231. fpc_val_int64_shortstr:=int64(Temp);
  1232. if vc.negative then
  1233. fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
  1234. {$endif EXCLUDE_COMPLEX_PROCS}
  1235. end;
  1236. Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
  1237. var
  1238. sp,ns : SizeInt;
  1239. u : SizeUInt;
  1240. digitsLeft : ALUSint;
  1241. prev: qword;
  1242. vc: ValCommon;
  1243. begin
  1244. fpc_val_qword_shortstr:=0;
  1245. sp:=InitVal(s,vc);
  1246. ns:=length(s);
  1247. If vc.negative or (sp>ns) or (s[sp]=#0) Then
  1248. begin
  1249. if vc.negative then sp:=vc.minusPos;
  1250. Code:=sp;
  1251. Exit;
  1252. end;
  1253. digitsLeft:=ValData.MaxDigits[0, vc.baseIndex, 3];
  1254. repeat
  1255. u:=SizeUint(ord(s[sp])-ord('0'));
  1256. if u>=length(ValData.ValueArray) then
  1257. break;
  1258. u:=ValData.ValueArray[u];
  1259. If u>=vc.base then
  1260. break;
  1261. dec(digitsLeft);
  1262. if digitsLeft<0 then
  1263. break;
  1264. prev:=fpc_val_qword_shortstr;
  1265. fpc_val_qword_shortstr:=fpc_val_qword_shortstr*vc.base+u;
  1266. inc(sp);
  1267. until sp>ns;
  1268. if digitsLeft<=0 then { Maybe an overflow. If so, step 1 digit back. }
  1269. begin
  1270. if sp<=ns then { If the loop was stopped not by sp>ns check... }
  1271. u:=ValData.ValueArray[ord(s[sp-1])-ord('0')]; { Then recover previous u. }
  1272. if prev>qword(High(qword)-u) div ValNonZeroBase(vc.base) then
  1273. dec(sp);
  1274. end;
  1275. code:=0;
  1276. if (sp<=ns) and (s[sp]<>#0) then
  1277. begin
  1278. Code:=sp;
  1279. fpc_val_qword_shortstr:=0;
  1280. end;
  1281. end;
  1282. {$endif CPU64}
  1283. {$if defined(CPU16) or defined(CPU8)}
  1284. Function fpc_val_longint_shortstr(Const S: ShortString; out Code: ValSInt): LongInt; [public, alias:'FPC_VAL_LONGINT_SHORTSTR']; compilerproc;
  1285. var u, temp, prev, maxprevvalue, maxnewvalue : longword;
  1286. vc : ValCommon;
  1287. const maxlongint=longword($7fffffff);
  1288. maxlongword=longword($ffffffff);
  1289. begin
  1290. fpc_val_longint_shortstr := 0;
  1291. Temp:=0;
  1292. Code:=InitVal(s,vc);
  1293. if (Code>length(s)) or (s[Code]=#0) then
  1294. exit;
  1295. maxprevvalue := maxlongword div vc.base;
  1296. if (vc.base = 10) then
  1297. maxnewvalue := maxlongint + ord(vc.negative)
  1298. else
  1299. maxnewvalue := maxlongword;
  1300. while Code<=Length(s) do
  1301. begin
  1302. u:=16;
  1303. case s[code] of
  1304. '0'..'f' : u:=ValData.ValueArray[ord(S[Code])-ord('0')];
  1305. #0 : break;
  1306. else
  1307. ;
  1308. end;
  1309. Prev:=Temp;
  1310. Temp:=Temp*longword(vc.base);
  1311. If (u >= vc.base) or
  1312. (longword(maxnewvalue-u) < temp) or
  1313. (prev > maxprevvalue) Then
  1314. Begin
  1315. fpc_val_longint_shortstr := 0;
  1316. Exit;
  1317. End;
  1318. Temp:=Temp+u;
  1319. inc(code);
  1320. end;
  1321. code:=0;
  1322. fpc_val_longint_shortstr:=longint(Temp);
  1323. If vc.Negative Then
  1324. fpc_val_longint_shortstr:=-fpc_val_longint_shortstr;
  1325. end;
  1326. Function fpc_val_longword_shortstr(Const S: ShortString; out Code: ValSInt): LongWord; [public, alias:'FPC_VAL_LONGWORD_SHORTSTR']; compilerproc;
  1327. var u, prev: LongWord;
  1328. vc: ValCommon;
  1329. const UpperLimit=High(longword);
  1330. begin
  1331. fpc_val_longword_shortstr:=0;
  1332. Code:=InitVal(s,vc);
  1333. If vc.Negative or (Code>length(s)) or (s[Code]=#0) Then
  1334. Exit;
  1335. while Code<=Length(s) do
  1336. begin
  1337. u:=16;
  1338. case s[code] of
  1339. '0'..'f' : u:=ValData.ValueArray[ord(S[Code])-ord('0')];
  1340. #0 : break;
  1341. else
  1342. ;
  1343. end;
  1344. If (u>=vc.base) or
  1345. (LongWord(UpperLimit-u) div LongWord(vc.Base)<fpc_val_longword_shortstr) then
  1346. begin
  1347. fpc_val_longword_shortstr:=0;
  1348. exit;
  1349. end;
  1350. fpc_val_longword_shortstr:=fpc_val_longword_shortstr*vc.base + u;
  1351. inc(code);
  1352. end;
  1353. code := 0;
  1354. end;
  1355. Function fpc_val_smallint_shortstr(Const S: ShortString; out Code: ValSInt): SmallInt; [public, alias:'FPC_VAL_SMALLINT_SHORTSTR']; compilerproc;
  1356. var u, temp, prev, maxprevvalue : word;
  1357. UnsignedUpperLimit: ValUInt;
  1358. vc: ValCommon;
  1359. begin
  1360. fpc_val_smallint_shortstr := 0;
  1361. Temp:=0;
  1362. Code:=InitVal(s,vc);
  1363. if (vc.base=10) or vc.negative then
  1364. UnsignedUpperLimit := Word(High(SmallInt))+Ord(vc.negative)
  1365. else
  1366. UnsignedUpperLimit := High(Word);
  1367. if (Code>length(s)) or (s[Code]=#0) then
  1368. exit;
  1369. maxprevvalue := High(Word) div vc.base;
  1370. while Code<=Length(s) do
  1371. begin
  1372. u:=16;
  1373. case s[code] of
  1374. '0'..'f' : u:=ValData.ValueArray[ord(S[Code])-ord('0')];
  1375. #0 : break;
  1376. else
  1377. ;
  1378. end;
  1379. Prev:=Temp;
  1380. Temp:=Temp*longword(vc.base);
  1381. If (u >= vc.base) or
  1382. (prev > maxPrevValue) or
  1383. ((Temp)>(UnsignedUpperLimit-u)) Then
  1384. Begin
  1385. fpc_val_smallint_shortstr := 0;
  1386. Exit
  1387. End;
  1388. Temp:=Temp+u;
  1389. inc(code);
  1390. end;
  1391. code:=0;
  1392. fpc_val_smallint_shortstr:=SmallInt(Temp);
  1393. If vc.Negative Then
  1394. fpc_val_smallint_shortstr:=-fpc_val_smallint_shortstr;
  1395. end;
  1396. Function fpc_val_word_shortstr(Const S: ShortString; out Code: ValSInt): Word; [public, alias:'FPC_VAL_WORD_SHORTSTR']; compilerproc;
  1397. var u, prev: word;
  1398. vc: ValCommon;
  1399. const UpperLimit=High(Word); //this preserves 3.2 (and earlier) behaviour
  1400. begin
  1401. fpc_val_word_shortstr:=0;
  1402. Code:=InitVal(s,vc);
  1403. If vc.Negative or (Code>length(s)) or (s[Code]=#0) Then
  1404. begin
  1405. if vc.Negative then Code:=vc.minusPos;
  1406. Exit;
  1407. end;
  1408. while Code<=Length(s) do
  1409. begin
  1410. u:=16;
  1411. case s[code] of
  1412. '0'..'f' : u:=ValData.ValueArray[ord(S[Code])-ord('0')];
  1413. #0 : break;
  1414. else
  1415. ;
  1416. end;
  1417. If (u>=vc.base) or
  1418. (Word(UpperLimit-u) div Word(vc.Base)<fpc_val_word_shortstr) then
  1419. begin
  1420. fpc_val_word_shortstr:=0;
  1421. exit;
  1422. end;
  1423. fpc_val_word_shortstr:=fpc_val_word_shortstr*vc.base + u;
  1424. inc(code);
  1425. end;
  1426. code := 0;
  1427. end;
  1428. {$endif CPU16 or CPU8}
  1429. {$ifndef FPUNONE}
  1430. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  1431. begin
  1432. fpc_Val_Real_ShortStr := val_real( s, code );
  1433. end;
  1434. {$endif FPUNONE}
  1435. {$ifndef FPC_STR_ENUM_INTERN}
  1436. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_SHORTSTR']; compilerproc;
  1437. type Psorted_array=^Tsorted_array;
  1438. Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1439. o:longint;
  1440. s:Pstring;
  1441. end;
  1442. Pstring_to_ord=^Tstring_to_ord;
  1443. Tstring_to_ord={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1444. count:longint;
  1445. data:array[0..0] of Tsorted_array;
  1446. end;
  1447. var l,r,l2,r2,m,sp,isp:SizeInt;
  1448. c:char;
  1449. begin
  1450. {Val for numbers accepts spaces at the start, so lets do the same
  1451. for enums. Skip spaces at the start of the string.}
  1452. sp:=1;
  1453. while (sp<=length(s)) and (s[sp]=' ') do
  1454. inc(sp);
  1455. { Let input be “abd” and sorted names be: _hm a aa ab aba abb abc abd ac ad b c
  1456. Start: L ┘R (R points PAST the last item in the range.)
  1457. After iteration 0 (“a” analyzed): L ┘R
  1458. After iteration 1 (“ab” analyzed): L ┘R
  1459. After iteration 2 (“abd” analyzed): L ┘R }
  1460. l:=0;
  1461. r:=Pstring_to_ord(str2ordindex)^.count;
  1462. dec(sp); { sp/isp are incremented at the beginning of the loop so that 'continue's advance sp/isp. }
  1463. isp:=0; { isp is the position without spaces. }
  1464. repeat
  1465. inc(sp);
  1466. if sp>length(s) then
  1467. break;
  1468. inc(isp);
  1469. c:=UpCase(s[sp]);
  1470. { Among all strings beginning with, say, ‘ab’, the ‘ab’ itself will be the first.
  1471. So after this check, “isp ≤ length(any string in the range)” is guaranteed. }
  1472. if isp>length(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[l].s^) then
  1473. begin
  1474. inc(l);
  1475. if l=r then
  1476. break;
  1477. end;
  1478. if UpCase(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[l].s^[isp])=c then { Shortcut: L may be already correct (enums often have common prefixes). }
  1479. begin
  1480. if l+1=r then { Shortcut: the only string left (enums often have different suffixes). }
  1481. continue;
  1482. end
  1483. else
  1484. begin
  1485. r2:=r; { Search for new L. }
  1486. repeat
  1487. m:=SizeUint(l+r2) div 2;
  1488. if UpCase(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[m].s^[isp])<c then
  1489. l:=m+1
  1490. else
  1491. r2:=m;
  1492. until l=r2;
  1493. if l=r then
  1494. break;
  1495. end;
  1496. if UpCase(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[r-1].s^[isp])=c then { Shortcut: R−1 may be already correct. }
  1497. continue;
  1498. l2:=l; { Search for new R. }
  1499. repeat
  1500. m:=SizeUint(l2+r) div 2;
  1501. if UpCase(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[m].s^[isp])<=c then
  1502. l2:=m+1
  1503. else
  1504. r:=m;
  1505. until l2=r;
  1506. if l=r then { Better not to make it the loop condition, or ‘continue’s may jump to it instead of the beginning. }
  1507. break;
  1508. until false;
  1509. if (l<r) and (isp=length(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[l].s^)) then
  1510. begin
  1511. code:=0;
  1512. exit(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[l].o);
  1513. end;
  1514. code:=sp;
  1515. result:=-1; { Formally undefined, but −1 is very likely the invalid value prone to crashing, which is better than accidentally working. }
  1516. end;
  1517. {Redeclare fpc_val_enum_shortstr for internal use in the system unit.}
  1518. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint;external name 'FPC_VAL_ENUM_SHORTSTR';
  1519. {$endif FPC_STR_ENUM_INTERN}
  1520. function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : ValSInt): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
  1521. {$ifdef EXCLUDE_COMPLEX_PROCS}
  1522. begin
  1523. runerror(217);
  1524. end;
  1525. {$else EXCLUDE_COMPLEX_PROCS}
  1526. const
  1527. MinInt64 : Int64 =-$8000000000000000;
  1528. MinInt64Edge : Int64 = (-$8000000000000000 + 10) div 10;
  1529. var
  1530. { to enable taking the address on the JVM target }
  1531. res : array[0..0] of Int64;
  1532. i,j,power,sign,len : longint;
  1533. FracOverflow : boolean;
  1534. begin
  1535. fpc_Val_Currency_ShortStr:=0;
  1536. res[0]:=0;
  1537. len:=Length(s);
  1538. Code:=1;
  1539. sign:=-1;
  1540. power:=0;
  1541. while True do
  1542. if Code > len then
  1543. exit
  1544. else
  1545. if s[Code] in [' ', #9] then
  1546. Inc(Code)
  1547. else
  1548. break;
  1549. { Read sign }
  1550. case s[Code] of
  1551. '+' : begin
  1552. Inc(Code);
  1553. end;
  1554. '-' : begin
  1555. sign:=+1;
  1556. Inc(Code);
  1557. end;
  1558. end;
  1559. { Read digits }
  1560. FracOverflow:=False;
  1561. i:=0;
  1562. while Code <= len do
  1563. begin
  1564. case s[Code] of
  1565. '0'..'9':
  1566. begin
  1567. j:=Ord(s[code])-Ord('0');
  1568. { check overflow }
  1569. if (res[0] >= MinInt64Edge) or (res[0] >= (MinInt64 + j) div 10) then
  1570. begin
  1571. res[0]:=res[0]*10 - j;
  1572. Inc(i);
  1573. end
  1574. else
  1575. if power = 0 then
  1576. { exit if integer part overflow }
  1577. exit
  1578. else
  1579. begin
  1580. if not FracOverflow and (j >= 5) and (res[0] > MinInt64) then
  1581. { round if first digit of fractional part overflow }
  1582. Dec(res[0]);
  1583. FracOverflow:=True;
  1584. end;
  1585. end;
  1586. '.':
  1587. begin
  1588. if power = 0 then
  1589. begin
  1590. power:=1;
  1591. i:=0;
  1592. end
  1593. else
  1594. exit;
  1595. end;
  1596. else
  1597. break;
  1598. end;
  1599. Inc(Code);
  1600. end;
  1601. if (i = 0) and (power = 0) then
  1602. exit;
  1603. if power <> 0 then
  1604. power:=i;
  1605. power:=4 - power;
  1606. { Exponent? }
  1607. if Code <= len then
  1608. if s[Code] in ['E', 'e'] then
  1609. begin
  1610. Inc(Code);
  1611. if Code > len then
  1612. exit;
  1613. i:=1;
  1614. case s[Code] of
  1615. '+':
  1616. Inc(Code);
  1617. '-':
  1618. begin
  1619. i:=-1;
  1620. Inc(Code);
  1621. end;
  1622. end;
  1623. { read exponent }
  1624. j:=0;
  1625. while Code <= len do
  1626. if s[Code] in ['0'..'9'] then
  1627. begin
  1628. if j > 4951 then
  1629. exit;
  1630. j:=j*10 + (Ord(s[code])-Ord('0'));
  1631. Inc(Code);
  1632. end
  1633. else
  1634. exit;
  1635. power:=power + j*i;
  1636. end
  1637. else
  1638. exit;
  1639. if power > 0 then
  1640. begin
  1641. for i:=1 to power do
  1642. if res[0] >= MinInt64 div 10 then
  1643. res[0]:=res[0]*10
  1644. else
  1645. exit;
  1646. end
  1647. else
  1648. for i:=1 to -power do
  1649. begin
  1650. if res[0] >= MinInt64 + 5 then
  1651. Dec(res[0], 5);
  1652. res[0]:=res[0] div 10;
  1653. end;
  1654. if sign <> 1 then
  1655. if res[0] > MinInt64 then
  1656. res[0]:=res[0]*sign
  1657. else
  1658. exit;
  1659. fpc_Val_Currency_ShortStr:=PCurrency(@res[0])^;
  1660. Code:=0;
  1661. end;
  1662. {$endif EXCLUDE_COMPLEX_PROCS}
  1663. {$ifndef FPC_HAS_SETSTRING_SHORTSTR}
  1664. {$define FPC_HAS_SETSTRING_SHORTSTR}
  1665. Procedure fpc_setstring_shortstr(Out S : Shortstring; Buf : PAnsiChar; Len : SizeInt); compilerproc;
  1666. begin
  1667. If Len > High(S) then
  1668. Len := High(S);
  1669. SetLength(S,Len);
  1670. If Buf<>Nil then
  1671. begin
  1672. Move (Buf[0],S[1],Len);
  1673. end;
  1674. end;
  1675. {$endif FPC_HAS_SETSTRING_SHORTSTR}
  1676. {$ifndef FPC_HAS_COMPARETEXT_SHORTSTR}
  1677. {$define FPC_HAS_COMPARETEXT_SHORTSTR}
  1678. function ShortCompareText(const S1, S2: shortstring): SizeInt;
  1679. var
  1680. c1, c2: Byte;
  1681. i: SizeInt;
  1682. L1, L2, Count: SizeInt;
  1683. P1, P2: PAnsiChar;
  1684. begin
  1685. L1 := Length(S1);
  1686. L2 := Length(S2);
  1687. if L1 > L2 then
  1688. Count := L2
  1689. else
  1690. Count := L1;
  1691. i := 0;
  1692. P1 := @S1[1];
  1693. P2 := @S2[1];
  1694. while i < count do
  1695. begin
  1696. c1 := byte(p1^);
  1697. c2 := byte(p2^);
  1698. if c1 <> c2 then
  1699. begin
  1700. if c1 in [97..122] then
  1701. Dec(c1, 32);
  1702. if c2 in [97..122] then
  1703. Dec(c2, 32);
  1704. if c1 <> c2 then
  1705. Break;
  1706. end;
  1707. Inc(P1); Inc(P2); Inc(I);
  1708. end;
  1709. if i < count then
  1710. ShortCompareText := c1 - c2
  1711. else
  1712. ShortCompareText := L1 - L2;
  1713. end;
  1714. {$endif FPC_HAS_COMPARETEXT_SHORTSTR}