sstrings.inc 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940
  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 : longint;
  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 : longint;
  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 : longint;
  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 : longint;
  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 : longint;
  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 : longint;
  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 : longint;
  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 : longint;
  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 : longint;
  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 : longint;
  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 : longint;
  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. {$I real2str.inc}
  411. {$endif}
  412. {$ifndef FPUNONE}
  413. procedure fpc_shortstr_float(d : ValReal;len,fr,rt : SizeInt;out s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; compilerproc;
  414. begin
  415. str_real(len,fr,d,treal_type(rt),s);
  416. end;
  417. {$endif}
  418. {$ifndef FPC_STR_ENUM_INTERN}
  419. function fpc_shortstr_enum_intern(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring): longint;
  420. { The following contains the TTypeInfo/TTypeData records from typinfo.pp
  421. specialized for the tkEnumeration case (and stripped of unused things). }
  422. type
  423. PPstring=^Pstring;
  424. Penum_typeinfo=^Tenum_typeinfo;
  425. Tenum_typeinfo={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  426. kind:byte; { always tkEnumeration }
  427. num_chars:byte;
  428. chars:array[0..0] of char; { variable length with size of num_chars }
  429. end;
  430. Penum_typedata=^Tenum_typedata;
  431. Tenum_typedata={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  432. ordtype:byte;
  433. { this seemingly extraneous inner record is here for alignment purposes, so
  434. that its data gets aligned properly (if FPC_REQUIRES_PROPER_ALIGNMENT is
  435. set }
  436. inner: {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  437. minvalue,maxvalue:longint;
  438. basetype:pointer; { required for alignment }
  439. end;
  440. { more data here, but not needed }
  441. end;
  442. { Pascal data types for the ordinal enum value to string table. It consists of a header
  443. that indicates what type of data the table stores, either a direct lookup table (when
  444. o = lookup) or a set of ordered (ordinal value, string) tuples (when o = search). }
  445. { A single entry in the set of ordered tuples }
  446. Psearch_data=^Tsearch_data;
  447. Tsearch_data={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  448. value:longint;
  449. name:Pstring;
  450. end;
  451. Penum_ord_to_string=^Tenum_ord_to_string;
  452. Tenum_ord_to_string={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  453. o:(lookup,search);
  454. case integer of
  455. 0: (lookup_data:array[0..0] of Pstring);
  456. 1: (num_entries:longint;
  457. search_data:array[0..0] of Tsearch_data);
  458. end;
  459. var
  460. enum_o2s : Penum_ord_to_string;
  461. header:Penum_typeinfo;
  462. body:Penum_typedata;
  463. res:Pshortstring;
  464. sorted_data:Psearch_data;
  465. spaces,i,m,h,l:longint;
  466. begin
  467. { set default return value }
  468. fpc_shortstr_enum_intern:=107;
  469. enum_o2s:=Penum_ord_to_string(ord2strindex);
  470. { depending on the type of table in ord2strindex retrieve the data }
  471. if (enum_o2s^.o=lookup) then
  472. begin
  473. { direct lookup table }
  474. header:=Penum_typeinfo(typinfo);
  475. { calculate address of enum rtti body: add the actual size of the
  476. enum_rtti_header, and then align. Use an alignment of 1 (which
  477. does nothing) in case FPC_REQUIRES_PROPER_ALIGNMENT is not set
  478. to avoid the need for an if in this situation }
  479. body:=Penum_typedata(align(ptruint(header) + 2 * sizeof(byte) { kind, num_chars } + header^.num_chars,
  480. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT} 1 {$else} sizeof(pointer) {$endif}));
  481. with (body^.inner) do
  482. begin
  483. { Bounds check for the ordinal value for this enum }
  484. if (ordinal<minvalue) or (ordinal>maxvalue) then
  485. exit;
  486. { make the ordinal index for lookup zero-based }
  487. dec(ordinal,minvalue);
  488. end;
  489. { temporarily disable range checking because of the access to the array[0..0]
  490. member of Tenum_ord_to_string_lookup }
  491. {$push}{$R-}
  492. res:=enum_o2s^.lookup_data[ordinal];
  493. {$pop}
  494. if (not assigned(res)) then
  495. exit;
  496. s:=res^;
  497. end
  498. else
  499. begin
  500. { The compiler did generate a sorted array of (ordvalue,Pstring) tuples }
  501. sorted_data:=@enum_o2s^.search_data;
  502. { Use a binary search to get the string }
  503. l:=0;
  504. { temporarily disable range checking because of the access to the array[0..0]
  505. member of Tenum_ord_to_string_search }
  506. {$push}{$R-}
  507. h:=enum_o2s^.num_entries-1;
  508. repeat
  509. m:=(l+h) div 2;
  510. if ordinal>sorted_data[m].value then
  511. l:=m+1
  512. else if ordinal<sorted_data[m].value then
  513. h:=m-1
  514. else
  515. break;
  516. if l>h then
  517. exit; { Ordinal value not found? Exit }
  518. until false;
  519. {$pop}
  520. s:=sorted_data[m].name^;
  521. end;
  522. { Pad the string with spaces if necessary }
  523. if (len>length(s)) then
  524. begin
  525. spaces:=len-length(s);
  526. for i:=1 to spaces do
  527. s[length(s)+i]:=' ';
  528. inc(byte(s[0]),spaces);
  529. end;
  530. fpc_shortstr_enum_intern:=0;
  531. end;
  532. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);[public,alias:'FPC_SHORTSTR_ENUM'];compilerproc;
  533. var
  534. res: longint;
  535. begin
  536. res:=fpc_shortstr_enum_intern(ordinal,len,typinfo,ord2strindex,s);
  537. if (res<>0) then
  538. runerror(107);
  539. end;
  540. { also define alias for internal use in the system unit }
  541. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);external name 'FPC_SHORTSTR_ENUM';
  542. {$endif FPC_SHORTSTR_ENUM_INTERN}
  543. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);[public,alias:'FPC_SHORTSTR_BOOL'];compilerproc;
  544. begin
  545. if b then
  546. s:='TRUE'
  547. else
  548. s:='FALSE';
  549. if length(s)<len then
  550. s:=space(len-length(s))+s;
  551. end;
  552. { also define alias for internal use in the system unit }
  553. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);external {$ifndef cpujvm}name 'FPC_SHORTSTR_BOOL'{$endif};
  554. procedure fpc_shortstr_currency({$ifdef cpujvm}constref{$endif} c : currency; len,f : SizeInt; out s : shortstring);[public,alias:'FPC_SHORTSTR_CURRENCY']; compilerproc;
  555. const
  556. MinLen = 8; { Minimal string length in scientific format }
  557. var
  558. buf : array[1..19] of char;
  559. i,j,k,reslen,tlen,sign,r,point : longint;
  560. ic : qword;
  561. begin
  562. fillchar(buf,length(buf),'0');
  563. { default value for length is -32767 }
  564. if len=-32767 then
  565. len:=25;
  566. if PInt64(@c)^ >= 0 then
  567. begin
  568. ic:=QWord(PInt64(@c)^);
  569. sign:=0;
  570. end
  571. else
  572. begin
  573. sign:=1;
  574. ic:=QWord(-PInt64(@c)^);
  575. end;
  576. { converting to integer string }
  577. tlen:=0;
  578. repeat
  579. Inc(tlen);
  580. buf[tlen]:=Chr(ic mod 10 + $30);
  581. ic:=ic div 10;
  582. until ic = 0;
  583. { calculating:
  584. reslen - length of result string,
  585. r - rounding or appending zeroes,
  586. point - place of decimal point }
  587. reslen:=tlen;
  588. if f <> 0 then
  589. Inc(reslen); { adding decimal point length }
  590. if f < 0 then
  591. begin
  592. { scientific format }
  593. Inc(reslen,5); { adding length of sign and exponent }
  594. if len < MinLen then
  595. len:=MinLen;
  596. r:=reslen-len;
  597. if reslen < len then
  598. reslen:=len;
  599. if r > 0 then
  600. begin
  601. reslen:=len;
  602. point:=tlen - r;
  603. end
  604. else
  605. point:=tlen;
  606. end
  607. else
  608. begin
  609. { fixed format }
  610. Inc(reslen, sign);
  611. { prepending fractional part with zeroes }
  612. while tlen < 5 do
  613. begin
  614. Inc(reslen);
  615. Inc(tlen);
  616. buf[tlen]:='0';
  617. end;
  618. { Currency have 4 digits in fractional part }
  619. r:=4 - f;
  620. point:=f;
  621. if point <> 0 then
  622. begin
  623. if point > 4 then
  624. point:=4;
  625. Inc(point);
  626. end;
  627. Dec(reslen,r);
  628. end;
  629. { rounding string if r > 0 }
  630. if r > 0 then
  631. begin
  632. k := 0;
  633. i := r+2;
  634. if i > tlen then
  635. i := tlen+1;
  636. if buf[i-2] >= '5' then
  637. begin
  638. if buf[i-1] < '9' then
  639. buf[i-1] := chr(ord(buf[i-1])+1)
  640. else
  641. begin
  642. buf[i-1] := '0';
  643. k := 1;
  644. end;
  645. end;
  646. If (k=1) and (buf[i-1]='0') then
  647. begin
  648. { 1.9996 rounded to two decimal digits after the decimal separator must result in
  649. 2.00, i.e. the rounding is propagated
  650. }
  651. while buf[i]='9' do
  652. begin
  653. buf[i]:='0';
  654. inc(i);
  655. end;
  656. buf[i]:=chr(Ord(buf[i])+1);
  657. { did we add another digit? This happens when rounding
  658. e.g. 99.9996 to two decimal digits after the decimal separator which should result in
  659. 100.00
  660. }
  661. if i>tlen then
  662. begin
  663. inc(reslen);
  664. inc(tlen);
  665. end;
  666. end;
  667. end;
  668. { preparing result string }
  669. if reslen<len then
  670. reslen:=len;
  671. if reslen>High(s) then
  672. begin
  673. if r < 0 then
  674. Inc(r, reslen - High(s));
  675. reslen:=High(s);
  676. end;
  677. SetLength(s,reslen);
  678. j:=reslen;
  679. if f<0 then
  680. begin
  681. { writing power of 10 part }
  682. if PInt64(@c)^ = 0 then
  683. k:=0
  684. else
  685. k:=tlen-5;
  686. if k >= 0 then
  687. s[j-2]:='+'
  688. else
  689. begin
  690. s[j-2]:='-';
  691. k:=-k;
  692. end;
  693. s[j]:=Chr(k mod 10 + $30);
  694. Dec(j);
  695. s[j]:=Chr(k div 10 + $30);
  696. Dec(j,2);
  697. s[j]:='E';
  698. Dec(j);
  699. end;
  700. { writing extra zeroes if r < 0 }
  701. while r < 0 do
  702. begin
  703. s[j]:='0';
  704. Dec(j);
  705. Inc(r);
  706. end;
  707. { writing digits and decimal point }
  708. for i:=r + 1 to tlen do
  709. begin
  710. Dec(point);
  711. if point = 0 then
  712. begin
  713. s[j]:='.';
  714. Dec(j);
  715. end;
  716. s[j]:=buf[i];
  717. Dec(j);
  718. end;
  719. { writing sign }
  720. if sign = 1 then
  721. begin
  722. s[j]:='-';
  723. Dec(j);
  724. end;
  725. { writing spaces }
  726. while j > 0 do
  727. begin
  728. s[j]:=' ';
  729. Dec(j);
  730. end;
  731. end;
  732. {
  733. Array Of Char Str() helpers
  734. }
  735. procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of char);compilerproc;
  736. var
  737. ss : shortstring;
  738. maxlen : SizeInt;
  739. begin
  740. int_str(v,ss);
  741. if length(ss)<len then
  742. ss:=space(len-length(ss))+ss;
  743. if length(ss)<high(a)+1 then
  744. maxlen:=length(ss)
  745. else
  746. maxlen:=high(a)+1;
  747. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  748. end;
  749. procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of char);compilerproc;
  750. var
  751. ss : shortstring;
  752. maxlen : SizeInt;
  753. begin
  754. int_str_unsigned(v,ss);
  755. if length(ss)<len then
  756. ss:=space(len-length(ss))+ss;
  757. if length(ss)<high(a)+1 then
  758. maxlen:=length(ss)
  759. else
  760. maxlen:=high(a)+1;
  761. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  762. end;
  763. {$ifndef CPU64}
  764. procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of char);compilerproc;
  765. var
  766. ss : shortstring;
  767. maxlen : SizeInt;
  768. begin
  769. int_str_unsigned(v,ss);
  770. if length(ss)<len then
  771. ss:=space(len-length(ss))+ss;
  772. if length(ss)<high(a)+1 then
  773. maxlen:=length(ss)
  774. else
  775. maxlen:=high(a)+1;
  776. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  777. end;
  778. procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of char);compilerproc;
  779. var
  780. ss : shortstring;
  781. maxlen : SizeInt;
  782. begin
  783. int_str(v,ss);
  784. if length(ss)<len then
  785. ss:=space(len-length(ss))+ss;
  786. if length(ss)<high(a)+1 then
  787. maxlen:=length(ss)
  788. else
  789. maxlen:=high(a)+1;
  790. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  791. end;
  792. {$endif CPU64}
  793. {$if defined(CPU16) or defined(CPU8)}
  794. procedure fpc_chararray_longword(v : longword;len : SizeInt;out a : array of char);compilerproc;
  795. var
  796. ss : shortstring;
  797. maxlen : SizeInt;
  798. begin
  799. int_str_unsigned(v,ss);
  800. if length(ss)<len then
  801. ss:=space(len-length(ss))+ss;
  802. if length(ss)<high(a)+1 then
  803. maxlen:=length(ss)
  804. else
  805. maxlen:=high(a)+1;
  806. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  807. end;
  808. procedure fpc_chararray_longint(v : longint;len : SizeInt;out a : array of char);compilerproc;
  809. var
  810. ss : shortstring;
  811. maxlen : SizeInt;
  812. begin
  813. int_str(v,ss);
  814. if length(ss)<len then
  815. ss:=space(len-length(ss))+ss;
  816. if length(ss)<high(a)+1 then
  817. maxlen:=length(ss)
  818. else
  819. maxlen:=high(a)+1;
  820. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  821. end;
  822. {$endif CPU16 or CPU8}
  823. {$ifndef FPUNONE}
  824. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of char);compilerproc;
  825. var
  826. ss : shortstring;
  827. maxlen : SizeInt;
  828. begin
  829. str_real(len,fr,d,treal_type(rt),ss);
  830. if length(ss)<high(a)+1 then
  831. maxlen:=length(ss)
  832. else
  833. maxlen:=high(a)+1;
  834. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  835. end;
  836. {$endif}
  837. {$ifndef FPC_STR_ENUM_INTERN}
  838. procedure fpc_chararray_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out a : array of char);compilerproc;
  839. var
  840. ss : shortstring;
  841. maxlen : SizeInt;
  842. begin
  843. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  844. if length(ss)<high(a)+1 then
  845. maxlen:=length(ss)
  846. else
  847. maxlen:=high(a)+1;
  848. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  849. end;
  850. {$endif not FPC_STR_ENUM_INTERN}
  851. procedure fpc_chararray_bool(b : boolean;len:sizeint;out a : array of char);compilerproc;
  852. var
  853. ss : shortstring;
  854. maxlen : SizeInt;
  855. begin
  856. fpc_shortstr_bool(b,len,ss);
  857. if length(ss)<high(a)+1 then
  858. maxlen:=length(ss)
  859. else
  860. maxlen:=high(a)+1;
  861. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  862. end;
  863. {$ifndef FPC_HAS_CHARARRAY_CURRENCY}
  864. {$define FPC_HAS_CHARARRAY_CURRENCY}
  865. procedure fpc_chararray_Currency(c : Currency;len,fr : SizeInt;out a : array of char);compilerproc;
  866. var
  867. ss : shortstring;
  868. maxlen : SizeInt;
  869. begin
  870. str(c:len:fr,ss);
  871. if length(ss)<high(a)+1 then
  872. maxlen:=length(ss)
  873. else
  874. maxlen:=high(a)+1;
  875. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  876. end;
  877. {$endif FPC_HAS_STR_CURRENCY}
  878. {*****************************************************************************
  879. Val() Functions
  880. *****************************************************************************}
  881. Function InitVal(const s:shortstring;out negativ:boolean;out base:byte):ValSInt;
  882. var
  883. Code : SizeInt;
  884. begin
  885. code:=1;
  886. negativ:=false;
  887. base:=10;
  888. if length(s)=0 then
  889. begin
  890. InitVal:=code;
  891. Exit;
  892. end;
  893. {Skip Spaces and Tab}
  894. while (code<=length(s)) and (s[code] in [' ',#9]) do
  895. inc(code);
  896. {Sign}
  897. case s[code] of
  898. '-' : begin
  899. negativ:=true;
  900. inc(code);
  901. end;
  902. '+' : inc(code);
  903. end;
  904. {Base}
  905. if code<=length(s) then
  906. begin
  907. case s[code] of
  908. '$',
  909. 'X',
  910. 'x' : begin
  911. base:=16;
  912. inc(code);
  913. end;
  914. '%' : begin
  915. base:=2;
  916. inc(code);
  917. end;
  918. '&' : begin
  919. Base:=8;
  920. inc(code);
  921. end;
  922. '0' : begin
  923. if (code < length(s)) and (s[code+1] in ['x', 'X']) then
  924. begin
  925. inc(code, 2);
  926. base := 16;
  927. end;
  928. end;
  929. end;
  930. end;
  931. { strip leading zeros }
  932. while ((code < length(s)) and (s[code] = '0')) do begin
  933. inc(code);
  934. end;
  935. InitVal:=code;
  936. end;
  937. Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
  938. var
  939. temp, prev, maxPrevValue, maxNewValue: ValUInt;
  940. base,u : byte;
  941. negative : boolean;
  942. begin
  943. fpc_Val_SInt_ShortStr := 0;
  944. Temp:=0;
  945. Code:=InitVal(s,negative,base);
  946. if Code>length(s) then
  947. exit;
  948. if (s[Code]=#0) then
  949. begin
  950. if (Code>1) and (s[Code-1]='0') then
  951. Code:=0;
  952. exit;
  953. end;
  954. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  955. if (base = 10) then
  956. maxNewValue := MaxSIntValue + ord(negative)
  957. else
  958. maxNewValue := MaxUIntValue;
  959. while Code<=Length(s) do
  960. begin
  961. case s[Code] of
  962. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  963. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  964. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  965. #0 : break;
  966. else
  967. u:=16;
  968. end;
  969. Prev := Temp;
  970. Temp := Temp*ValUInt(base);
  971. If (u >= base) or
  972. (ValUInt(maxNewValue-u) < Temp) or
  973. (prev > maxPrevValue) Then
  974. Begin
  975. fpc_Val_SInt_ShortStr := 0;
  976. Exit
  977. End;
  978. Temp:=Temp+u;
  979. inc(code);
  980. end;
  981. code := 0;
  982. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  983. If Negative Then
  984. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  985. If Not(Negative) and (base <> 10) Then
  986. {sign extend the result to allow proper range checking}
  987. Case DestSize of
  988. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  989. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  990. {$ifdef cpu64}
  991. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);
  992. {$endif cpu64}
  993. End;
  994. end;
  995. {$ifndef FPC_HAS_INT_VAL_SINT_SHORTSTR}
  996. {$define FPC_HAS_INT_VAL_SINT_SHORTSTR}
  997. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  998. { we have to pass the DestSize parameter on (JM) }
  999. Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  1000. {$endif FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1001. Function fpc_Val_UInt_Shortstr(Const S: ShortString; out Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; compilerproc;
  1002. var
  1003. prev : ValUInt;
  1004. base,u : byte;
  1005. negative : boolean;
  1006. begin
  1007. fpc_Val_UInt_Shortstr:=0;
  1008. Code:=InitVal(s,negative,base);
  1009. If Negative or (Code>length(s)) Then
  1010. Exit;
  1011. if (s[Code]=#0) then
  1012. begin
  1013. if (Code>1) and (s[Code-1]='0') then
  1014. Code:=0;
  1015. exit;
  1016. end;
  1017. while Code<=Length(s) do
  1018. begin
  1019. case s[Code] of
  1020. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1021. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1022. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1023. #0 : break;
  1024. else
  1025. u:=16;
  1026. end;
  1027. prev := fpc_Val_UInt_Shortstr;
  1028. If (u>=base) or
  1029. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
  1030. begin
  1031. fpc_Val_UInt_Shortstr:=0;
  1032. exit;
  1033. end;
  1034. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  1035. inc(code);
  1036. end;
  1037. code := 0;
  1038. end;
  1039. {$ifndef CPU64}
  1040. Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
  1041. var u, temp, prev, maxprevvalue, maxnewvalue : qword;
  1042. base : byte;
  1043. negative : boolean;
  1044. const maxint64=qword($7fffffffffffffff);
  1045. maxqword=qword($ffffffffffffffff);
  1046. begin
  1047. fpc_val_int64_shortstr := 0;
  1048. Temp:=0;
  1049. Code:=InitVal(s,negative,base);
  1050. if Code>length(s) then
  1051. exit;
  1052. if (s[Code]=#0) then
  1053. begin
  1054. if (Code>1) and (s[Code-1]='0') then
  1055. Code:=0;
  1056. exit;
  1057. end;
  1058. maxprevvalue := maxqword div base;
  1059. if (base = 10) then
  1060. maxnewvalue := maxint64 + ord(negative)
  1061. else
  1062. maxnewvalue := maxqword;
  1063. while Code<=Length(s) do
  1064. begin
  1065. case s[Code] of
  1066. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1067. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1068. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1069. #0 : break;
  1070. else
  1071. u:=16;
  1072. end;
  1073. Prev:=Temp;
  1074. Temp:=Temp*qword(base);
  1075. If (u >= base) or
  1076. (qword(maxnewvalue-u) < temp) or
  1077. (prev > maxprevvalue) Then
  1078. Begin
  1079. fpc_val_int64_shortstr := 0;
  1080. Exit
  1081. End;
  1082. Temp:=Temp+u;
  1083. inc(code);
  1084. end;
  1085. code:=0;
  1086. fpc_val_int64_shortstr:=int64(Temp);
  1087. If Negative Then
  1088. fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
  1089. end;
  1090. Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
  1091. var u, prev: QWord;
  1092. base : byte;
  1093. negative : boolean;
  1094. const maxqword=qword($ffffffffffffffff);
  1095. begin
  1096. fpc_val_qword_shortstr:=0;
  1097. Code:=InitVal(s,negative,base);
  1098. If Negative or (Code>length(s)) Then
  1099. Exit;
  1100. if (s[Code]=#0) then
  1101. begin
  1102. if (Code>1) and (s[Code-1]='0') then
  1103. Code:=0;
  1104. exit;
  1105. end;
  1106. while Code<=Length(s) do
  1107. begin
  1108. case s[Code] of
  1109. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1110. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1111. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1112. #0 : break;
  1113. else
  1114. u:=16;
  1115. end;
  1116. prev := fpc_val_qword_shortstr;
  1117. If (u>=base) or
  1118. ((QWord(maxqword-u) div QWord(base))<prev) then
  1119. Begin
  1120. fpc_val_qword_shortstr := 0;
  1121. Exit
  1122. End;
  1123. fpc_val_qword_shortstr:=fpc_val_qword_shortstr*QWord(base) + u;
  1124. inc(code);
  1125. end;
  1126. code := 0;
  1127. end;
  1128. {$endif CPU64}
  1129. {$if defined(CPU16) or defined(CPU8)}
  1130. Function fpc_val_longint_shortstr(Const S: ShortString; out Code: ValSInt): LongInt; [public, alias:'FPC_VAL_LONGINT_SHORTSTR']; compilerproc;
  1131. var u, temp, prev, maxprevvalue, maxnewvalue : longword;
  1132. base : byte;
  1133. negative : boolean;
  1134. const maxlongint=longword($7fffffff);
  1135. maxlongword=longword($ffffffff);
  1136. begin
  1137. fpc_val_longint_shortstr := 0;
  1138. Temp:=0;
  1139. Code:=InitVal(s,negative,base);
  1140. if Code>length(s) then
  1141. exit;
  1142. if (s[Code]=#0) then
  1143. begin
  1144. if (Code>1) and (s[Code-1]='0') then
  1145. Code:=0;
  1146. exit;
  1147. end;
  1148. maxprevvalue := maxlongword div base;
  1149. if (base = 10) then
  1150. maxnewvalue := maxlongint + ord(negative)
  1151. else
  1152. maxnewvalue := maxlongword;
  1153. while Code<=Length(s) do
  1154. begin
  1155. case s[Code] of
  1156. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1157. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1158. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1159. #0 : break;
  1160. else
  1161. u:=16;
  1162. end;
  1163. Prev:=Temp;
  1164. Temp:=Temp*longword(base);
  1165. If (u >= base) or
  1166. (longword(maxnewvalue-u) < temp) or
  1167. (prev > maxprevvalue) Then
  1168. Begin
  1169. fpc_val_longint_shortstr := 0;
  1170. Exit
  1171. End;
  1172. Temp:=Temp+u;
  1173. inc(code);
  1174. end;
  1175. code:=0;
  1176. fpc_val_longint_shortstr:=longint(Temp);
  1177. If Negative Then
  1178. fpc_val_longint_shortstr:=-fpc_val_longint_shortstr;
  1179. end;
  1180. Function fpc_val_longword_shortstr(Const S: ShortString; out Code: ValSInt): LongWord; [public, alias:'FPC_VAL_LONGWORD_SHORTSTR']; compilerproc;
  1181. var u, prev: LongWord;
  1182. base : byte;
  1183. negative : boolean;
  1184. const maxlongword=longword($ffffffff);
  1185. begin
  1186. fpc_val_longword_shortstr:=0;
  1187. Code:=InitVal(s,negative,base);
  1188. If Negative or (Code>length(s)) Then
  1189. Exit;
  1190. if (s[Code]=#0) then
  1191. begin
  1192. if (Code>1) and (s[Code-1]='0') then
  1193. Code:=0;
  1194. exit;
  1195. end;
  1196. while Code<=Length(s) do
  1197. begin
  1198. case s[Code] of
  1199. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  1200. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  1201. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  1202. #0 : break;
  1203. else
  1204. u:=16;
  1205. end;
  1206. prev := fpc_val_longword_shortstr;
  1207. If (u>=base) or
  1208. ((LongWord(maxlongword-u) div LongWord(base))<prev) then
  1209. Begin
  1210. fpc_val_longword_shortstr := 0;
  1211. Exit
  1212. End;
  1213. fpc_val_longword_shortstr:=fpc_val_longword_shortstr*LongWord(base) + u;
  1214. inc(code);
  1215. end;
  1216. code := 0;
  1217. end;
  1218. {$endif CPU16 or CPU8}
  1219. {$ifndef FPUNONE}
  1220. const
  1221. {$ifdef FPC_HAS_TYPE_EXTENDED}
  1222. valmaxexpnorm=4932;
  1223. {$else}
  1224. {$ifdef FPC_HAS_TYPE_DOUBLE}
  1225. valmaxexpnorm=308;
  1226. {$else}
  1227. {$ifdef FPC_HAS_TYPE_SINGLE}
  1228. valmaxexpnorm=38;
  1229. {$else}
  1230. {$error Unknown floating point precision }
  1231. {$endif}
  1232. {$endif}
  1233. {$endif}
  1234. {$endif}
  1235. {$ifndef FPUNONE}
  1236. (******************
  1237. Derived from: ".\Free Pascal\source\rtl\inc\genmath.inc"
  1238. Origin: "fast 10^n routine"
  1239. function FPower10(val: Extended; Power: Longint): Extended;
  1240. Changes:
  1241. > adapted to "ValReal", so float can be single/double/extended
  1242. > slightly changed arrays [redundant 58+2 float constants gone away]
  1243. > added some checks etc..
  1244. Notes:
  1245. > denormalization and overflow should go smooth if corresponding
  1246. FPU exceptions are masked [no external care needed by now]
  1247. > adaption to real48 and real128 is not hard if one needed
  1248. ******************)
  1249. //
  1250. function mul_by_power10(x:ValReal;power:integer):ValReal;
  1251. //
  1252. // result:=X*(10^power)
  1253. //
  1254. // Routine achieves result with no more than 3 floating point mul/div's.
  1255. // Up to ABS(power)=31, only 1 floating point mul/div is needed.
  1256. //
  1257. // Limitations:
  1258. // for ValReal=extended : power=-5119..+5119
  1259. // for ValReal=double : power=-319..+319
  1260. // for ValReal=single : power=-63..+63
  1261. //
  1262. // If "power" is beyond this limits, routine gives up and returns 0/+INF/-INF.
  1263. // This is not generally correct, but should be ok when routine is used only
  1264. // as "VAL"-helper, since "x" exponent is reasonably close to 0 in this case.
  1265. //
  1266. //==================================
  1267. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1268. {$ERROR C_HIGH_EXPBITS_5TO8 declared somewhere in scope}
  1269. {$ENDIF}
  1270. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1271. {$ERROR C_HIGH_EXPBITS_9ANDUP declared somewhere in scope}
  1272. {$ENDIF}
  1273. {$IF SIZEOF(ValReal)=10}
  1274. //==================================
  1275. // assuming "type ValReal=extended;"
  1276. //
  1277. const
  1278. C_MAX_POWER = 5119;
  1279. C_HIGH_EXPBITS_5TO8 = 15;
  1280. C_HIGH_EXPBITS_9ANDUP = 9;
  1281. {$ELSEIF SIZEOF(ValReal)=8}
  1282. //==================================
  1283. // assuming "type ValReal=double;"
  1284. //
  1285. const
  1286. C_MAX_POWER = 319;
  1287. C_HIGH_EXPBITS_5TO8 = 9;
  1288. {$ELSEIF SIZEOF(ValReal)=4}
  1289. //==================================
  1290. // assuming "type ValReal=single;"
  1291. //
  1292. const
  1293. C_MAX_POWER = 63;
  1294. {$ELSE}
  1295. //==================================
  1296. // assuming "ValReal=?"
  1297. //
  1298. {$ERROR Unsupported ValReal type}
  1299. {$ENDIF}
  1300. //==================================
  1301. const
  1302. C_INFTYP = ValReal( 1.0/0.0);
  1303. C_INFTYM = ValReal(-1.0/0.0);
  1304. mul_expbits_0_to_4:packed array[0..31]of ValReal=(
  1305. 1E0, 1E1, 1E2, 1E3,
  1306. 1E4, 1E5, 1E6, 1E7,
  1307. 1E8, 1E9, 1E10, 1E11,
  1308. 1E12, 1E13, 1E14, 1E15,
  1309. 1E16, 1E17, 1E18, 1E19,
  1310. 1E20, 1E21, 1E22, 1E23,
  1311. 1E24, 1E25, 1E26, 1E27,
  1312. 1E28, 1E29, 1E30, 1E31);
  1313. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1314. mul_expbits_5_to_8:packed array[1..C_HIGH_EXPBITS_5TO8] of ValReal=(
  1315. 1E32, 1E64, 1E96, 1E128,
  1316. 1E160, 1E192, 1E224, 1E256, 1E288
  1317. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)},
  1318. 1E320, 1E352, 1E384, 1E416, 1E448, 1E480
  1319. {$ENDIF});
  1320. {$ELSE}
  1321. mul_expbits_5_to_8:ValReal=1E32;
  1322. {$ENDIF}
  1323. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1324. mul_expbits_9_and_up:packed array[1..C_HIGH_EXPBITS_9ANDUP] of ValReal=(
  1325. 1E512, 1E1024, 1E1536, 1E2048,
  1326. 1E2560, 1E3072, 1E3584, 1E4096,
  1327. 1E4608);
  1328. {$ENDIF}
  1329. begin
  1330. if power=0 then mul_by_power10:=x else
  1331. if power<-C_MAX_POWER then mul_by_power10:=0 else
  1332. if power>C_MAX_POWER then
  1333. if x<0 then mul_by_power10:=C_INFTYM else
  1334. if x>0 then mul_by_power10:=C_INFTYP else mul_by_power10:=0
  1335. else
  1336. if power<0 then
  1337. begin
  1338. power:=-power;
  1339. mul_by_power10:=x/mul_expbits_0_to_4[power and $1F];
  1340. power:=(power shr 5);
  1341. if power=0 then exit;
  1342. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1343. if power and $F<>0 then
  1344. mul_by_power10:=
  1345. mul_by_power10/mul_expbits_5_to_8[power and $F];
  1346. {$ELSE} // "single", power<>0, so always div
  1347. mul_by_power10:=mul_by_power10/mul_expbits_5_to_8;
  1348. {$ENDIF}
  1349. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1350. power:=(power shr 4);
  1351. if power<>0 then
  1352. mul_by_power10:=
  1353. mul_by_power10/mul_expbits_9_and_up[power];
  1354. {$ENDIF}
  1355. end
  1356. else
  1357. begin
  1358. mul_by_power10:=x*mul_expbits_0_to_4[power and $1F];
  1359. power:=(power shr 5);
  1360. if power=0 then exit;
  1361. {$IF DECLARED(C_HIGH_EXPBITS_5TO8)}
  1362. if power and $F<>0 then
  1363. mul_by_power10:=
  1364. mul_by_power10*mul_expbits_5_to_8[power and $F];
  1365. {$ELSE} // "single", power<>0, so always mul
  1366. mul_by_power10:=mul_by_power10*mul_expbits_5_to_8;
  1367. {$ENDIF}
  1368. {$IF DECLARED(C_HIGH_EXPBITS_9ANDUP)}
  1369. power:=(power shr 4);
  1370. if power<>0 then
  1371. mul_by_power10:=
  1372. mul_by_power10*mul_expbits_9_and_up[power];
  1373. {$ENDIF}
  1374. end;
  1375. end;
  1376. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  1377. var
  1378. hd,
  1379. sign : valreal;
  1380. esign,
  1381. exponent,
  1382. decpoint : SizeInt;
  1383. flags : byte;
  1384. begin
  1385. fpc_Val_Real_ShortStr:=0.0;
  1386. code:=1;
  1387. exponent:=0;
  1388. decpoint:=0;
  1389. esign:=1;
  1390. flags:=0;
  1391. sign:=1;
  1392. while (code<=length(s)) and (s[code] in [' ',#9]) do
  1393. inc(code);
  1394. if code<=length(s) then
  1395. case s[code] of
  1396. '+' : inc(code);
  1397. '-' : begin
  1398. sign:=-1;
  1399. inc(code);
  1400. end;
  1401. end;
  1402. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  1403. begin
  1404. { Read integer part }
  1405. flags:=flags or 1;
  1406. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  1407. inc(code);
  1408. end;
  1409. { Decimal ? }
  1410. if (length(s)>=code) and (s[code]='.') then
  1411. begin
  1412. inc(code);
  1413. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  1414. begin
  1415. { Read fractional part. }
  1416. flags:=flags or 2;
  1417. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  1418. inc(decpoint);
  1419. inc(code);
  1420. end;
  1421. end;
  1422. { Again, read integer and fractional part}
  1423. if flags=0 then
  1424. begin
  1425. fpc_Val_Real_ShortStr:=0.0;
  1426. exit;
  1427. end;
  1428. { Exponent ? }
  1429. if (length(s)>=code) and (s[code] in ['e','E']) then
  1430. begin
  1431. inc(code);
  1432. if Length(s) >= code then
  1433. if s[code]='+' then
  1434. inc(code)
  1435. else
  1436. if s[code]='-' then
  1437. begin
  1438. esign:=-1;
  1439. inc(code);
  1440. end;
  1441. if (length(s)<code) or not(s[code] in ['0'..'9']) then
  1442. begin
  1443. fpc_Val_Real_ShortStr:=0.0;
  1444. exit;
  1445. end;
  1446. while (length(s)>=code) and (s[code] in ['0'..'9']) do
  1447. begin
  1448. exponent:=exponent*10;
  1449. exponent:=exponent+ord(s[code])-ord('0');
  1450. inc(code);
  1451. end;
  1452. end;
  1453. { adjust exponent based on decimal point }
  1454. if esign>0 then
  1455. begin
  1456. dec(exponent,decpoint);
  1457. if (exponent<0) then
  1458. begin
  1459. esign:=-1;
  1460. exponent:=-exponent;
  1461. end
  1462. end
  1463. else
  1464. inc(exponent,decpoint);
  1465. { evaluate sign }
  1466. { (before exponent, because the exponent may turn it into a denormal) }
  1467. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*sign;
  1468. { Calculate Exponent }
  1469. hd:=1.0;
  1470. { the magnitude range maximum (normal) is lower in absolute value than the }
  1471. { the magnitude range minimum (denormal). E.g. an extended value can go }
  1472. { up to 1E4932, but "down" to 1E-4951. So make sure that we don't try to }
  1473. { calculate 1E4951 as factor, since that would overflow and result in 0. }
  1474. if (exponent>valmaxexpnorm-2) then
  1475. begin
  1476. hd:=mul_by_power10(hd,valmaxexpnorm-2);
  1477. if esign>0 then
  1478. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  1479. else
  1480. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  1481. dec(exponent,valmaxexpnorm-2);
  1482. hd:=1.0;
  1483. end;
  1484. hd:=mul_by_power10(hd,exponent);
  1485. if esign>0 then
  1486. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  1487. else
  1488. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  1489. { Not all characters are read ? }
  1490. if length(s)>=code then
  1491. begin
  1492. fpc_Val_Real_ShortStr:=0.0;
  1493. exit;
  1494. end;
  1495. { success ! }
  1496. code:=0;
  1497. end;
  1498. {$endif}
  1499. {$ifndef FPC_STR_ENUM_INTERN}
  1500. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_SHORTSTR']; compilerproc;
  1501. function string_compare(const s1,s2:shortstring):sizeint;
  1502. {We cannot use the > and < operators to compare a string here, because we if the string is
  1503. not found in the enum, we need to return the position of error in "code". Code equals the
  1504. highest matching character of all string compares, which is only known inside the string
  1505. comparison.}
  1506. var i,l:byte;
  1507. c1,c2:char;
  1508. begin
  1509. l:=length(s1);
  1510. if length(s1)>length(s2) then
  1511. l:=length(s2);
  1512. i:=1;
  1513. while i<=l do
  1514. begin
  1515. c1:=s1[i];
  1516. c2:=s2[i];
  1517. if c1<>c2 then
  1518. break;
  1519. inc(i);
  1520. end;
  1521. if i>code then
  1522. code:=i;
  1523. if i<=l then
  1524. string_compare:=byte(c1)-byte(c2)
  1525. else
  1526. string_compare:=length(s1)-length(s2);
  1527. end;
  1528. type Psorted_array=^Tsorted_array;
  1529. Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1530. o:longint;
  1531. s:Pstring;
  1532. end;
  1533. Pstring_to_ord=^Tstring_to_ord;
  1534. Tstring_to_ord={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1535. count:longint;
  1536. data:array[0..0] of Tsorted_array;
  1537. end;
  1538. var l,h,m:cardinal;
  1539. c:sizeint;
  1540. sorted_array:^Tsorted_array;
  1541. spaces:byte;
  1542. t:shortstring;
  1543. begin
  1544. {Val for numbers accepts spaces at the start, so lets do the same
  1545. for enums. Skip spaces at the start of the string.}
  1546. spaces:=1;
  1547. code:=1;
  1548. while (spaces<=length(s)) and (s[spaces]=' ') do
  1549. inc(spaces);
  1550. t:=upcase(copy(s,spaces,255));
  1551. sorted_array:=pointer(@Pstring_to_ord(str2ordindex)^.data);
  1552. {Use a binary search to get the string.}
  1553. l:=1;
  1554. h:=Pstring_to_ord(str2ordindex)^.count;
  1555. repeat
  1556. m:=(l+h) div 2;
  1557. c:=string_compare(t,upcase(sorted_array[m-1].s^));
  1558. if c>0 then
  1559. l:=m+1
  1560. else if c<0 then
  1561. h:=m-1
  1562. else
  1563. break;
  1564. if l>h then
  1565. begin
  1566. {Not found...}
  1567. inc(code,spaces-1); {Add skipped spaces again.}
  1568. {The result of val in case of error is undefined, don't assign a function result.}
  1569. exit;
  1570. end;
  1571. until false;
  1572. code:=0;
  1573. fpc_val_enum_shortstr:=sorted_array[m-1].o;
  1574. end;
  1575. {Redeclare fpc_val_enum_shortstr for internal use in the system unit.}
  1576. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint;external name 'FPC_VAL_ENUM_SHORTSTR';
  1577. {$endif FPC_STR_ENUM_INTERN}
  1578. function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : ValSInt): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
  1579. const
  1580. MaxInt64 : Int64 = $7FFFFFFFFFFFFFFF;
  1581. Int64Edge : Int64 = ($7FFFFFFFFFFFFFFF - 10) div 10;
  1582. Int64Edge2 : Int64 = $7FFFFFFFFFFFFFFF div 10;
  1583. var
  1584. { to enable taking the address on the JVM target }
  1585. res : array[0..0] of Int64;
  1586. i,j,power,sign,len : longint;
  1587. FracOverflow : boolean;
  1588. begin
  1589. fpc_Val_Currency_ShortStr:=0;
  1590. res[0]:=0;
  1591. len:=Length(s);
  1592. Code:=1;
  1593. sign:=1;
  1594. power:=0;
  1595. while True do
  1596. if Code > len then
  1597. exit
  1598. else
  1599. if s[Code] in [' ', #9] then
  1600. Inc(Code)
  1601. else
  1602. break;
  1603. { Read sign }
  1604. case s[Code] of
  1605. '+' : Inc(Code);
  1606. '-' : begin
  1607. sign:=-1;
  1608. inc(code);
  1609. end;
  1610. end;
  1611. { Read digits }
  1612. FracOverflow:=False;
  1613. i:=0;
  1614. while Code <= len do
  1615. begin
  1616. case s[Code] of
  1617. '0'..'9':
  1618. begin
  1619. j:=Ord(s[code])-Ord('0');
  1620. { check overflow }
  1621. if (res[0] <= Int64Edge) or (res[0] <= (MaxInt64 - j) div 10) then
  1622. begin
  1623. res[0]:=res[0]*10 + j;
  1624. Inc(i);
  1625. end
  1626. else
  1627. if power = 0 then
  1628. { exit if integer part overflow }
  1629. exit
  1630. else
  1631. begin
  1632. if not FracOverflow and (j >= 5) and (res[0] < MaxInt64) then
  1633. { round if first digit of fractional part overflow }
  1634. Inc(res[0]);
  1635. FracOverflow:=True;
  1636. end;
  1637. end;
  1638. '.':
  1639. begin
  1640. if power = 0 then
  1641. begin
  1642. power:=1;
  1643. i:=0;
  1644. end
  1645. else
  1646. exit;
  1647. end;
  1648. else
  1649. break;
  1650. end;
  1651. Inc(Code);
  1652. end;
  1653. if (i = 0) and (power = 0) then
  1654. exit;
  1655. if power <> 0 then
  1656. power:=i;
  1657. power:=4 - power;
  1658. { Exponent? }
  1659. if Code <= len then
  1660. if s[Code] in ['E', 'e'] then
  1661. begin
  1662. Inc(Code);
  1663. if Code > len then
  1664. exit;
  1665. i:=1;
  1666. case s[Code] of
  1667. '+':
  1668. Inc(Code);
  1669. '-':
  1670. begin
  1671. i:=-1;
  1672. Inc(Code);
  1673. end;
  1674. end;
  1675. { read exponent }
  1676. j:=0;
  1677. while Code <= len do
  1678. if s[Code] in ['0'..'9'] then
  1679. begin
  1680. if j > 4951 then
  1681. exit;
  1682. j:=j*10 + (Ord(s[code])-Ord('0'));
  1683. Inc(Code);
  1684. end
  1685. else
  1686. exit;
  1687. power:=power + j*i;
  1688. end
  1689. else
  1690. exit;
  1691. if power > 0 then
  1692. begin
  1693. for i:=1 to power do
  1694. if res[0] <= Int64Edge2 then
  1695. res[0]:=res[0]*10
  1696. else
  1697. exit;
  1698. end
  1699. else
  1700. for i:=1 to -power do
  1701. begin
  1702. if res[0] <= MaxInt64 - 5 then
  1703. Inc(res[0], 5);
  1704. res[0]:=res[0] div 10;
  1705. end;
  1706. res[0]:=res[0]*sign;
  1707. fpc_Val_Currency_ShortStr:=PCurrency(@res[0])^;
  1708. Code:=0;
  1709. end;
  1710. {$ifndef FPC_HAS_SETSTRING_SHORTSTR}
  1711. {$define FPC_HAS_SETSTRING_SHORTSTR}
  1712. Procedure SetString (Out S : Shortstring; Buf : PChar; Len : SizeInt);
  1713. begin
  1714. If Len > High(S) then
  1715. Len := High(S);
  1716. SetLength(S,Len);
  1717. If Buf<>Nil then
  1718. begin
  1719. Move (Buf[0],S[1],Len);
  1720. end;
  1721. end;
  1722. {$endif FPC_HAS_SETSTRING_SHORTSTR}
  1723. {$ifndef FPC_HAS_COMPARETEXT_SHORTSTR}
  1724. {$define FPC_HAS_COMPARETEXT_SHORTSTR}
  1725. function ShortCompareText(const S1, S2: shortstring): SizeInt;
  1726. var
  1727. c1, c2: Byte;
  1728. i: Integer;
  1729. L1, L2, Count: SizeInt;
  1730. P1, P2: PChar;
  1731. begin
  1732. L1 := Length(S1);
  1733. L2 := Length(S2);
  1734. if L1 > L2 then
  1735. Count := L2
  1736. else
  1737. Count := L1;
  1738. i := 0;
  1739. P1 := @S1[1];
  1740. P2 := @S2[1];
  1741. while i < count do
  1742. begin
  1743. c1 := byte(p1^);
  1744. c2 := byte(p2^);
  1745. if c1 <> c2 then
  1746. begin
  1747. if c1 in [97..122] then
  1748. Dec(c1, 32);
  1749. if c2 in [97..122] then
  1750. Dec(c2, 32);
  1751. if c1 <> c2 then
  1752. Break;
  1753. end;
  1754. Inc(P1); Inc(P2); Inc(I);
  1755. end;
  1756. if i < count then
  1757. ShortCompareText := c1 - c2
  1758. else
  1759. ShortCompareText := L1 - L2;
  1760. end;
  1761. {$endif FPC_HAS_COMPARETEXT_SHORTSTR}