sstrings.inc 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916
  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 {$ifdef VER3_0}delete{$else}fpc_shortstr_delete{$endif}(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 {$ifdef ver3_0}insert{$else}fpc_shortstr_insert{$endif}(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 {$ifdef ver3_0}insert{$else}fpc_shortstr_insert_char{$endif}(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. {$ifndef VER3_0}
  450. tkInt64,tkQWord,
  451. {$endif VER3_0}
  452. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar: (
  453. OrdType : Byte;
  454. case TTypeKind of
  455. tkInteger,tkChar,tkEnumeration,tkBool,tkWChar: (
  456. MinValue,MaxValue : Longint;
  457. case TTypeKind of
  458. tkEnumeration: (
  459. BaseTypeRef : pointer
  460. );
  461. {$ifndef VER3_0}
  462. {tkBool with OrdType=otSQWord }
  463. tkInt64:
  464. (MinInt64Value, MaxInt64Value: Int64);
  465. {tkBool with OrdType=otUQWord }
  466. tkQWord:
  467. (MinQWordValue, MaxQWordValue: QWord);
  468. {$endif VER3_0}
  469. );
  470. );
  471. { more data here, but not needed }
  472. end;
  473. { Pascal data types for the ordinal enum value to string table. It consists of a header
  474. that indicates what type of data the table stores, either a direct lookup table (when
  475. o = lookup) or a set of ordered (ordinal value, string) tuples (when o = search). }
  476. { A single entry in the set of ordered tuples }
  477. Psearch_data=^Tsearch_data;
  478. Tsearch_data={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  479. value:longint;
  480. name:Pstring;
  481. end;
  482. Penum_ord_to_string=^Tenum_ord_to_string;
  483. Tenum_ord_to_string={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  484. o:(lookup,search);
  485. case integer of
  486. 0: (lookup_data:array[0..0] of Pstring);
  487. 1: (num_entries:longint;
  488. search_data:array[0..0] of Tsearch_data);
  489. end;
  490. {$pop}
  491. var
  492. enum_o2s : Penum_ord_to_string;
  493. header:Penum_typeinfo;
  494. body:Penum_typedata;
  495. res:Pshortstring;
  496. sorted_data:Psearch_data;
  497. spaces,i,m,h,l:longint;
  498. begin
  499. { set default return value }
  500. fpc_shortstr_enum_intern:=107;
  501. enum_o2s:=Penum_ord_to_string(ord2strindex);
  502. { depending on the type of table in ord2strindex retrieve the data }
  503. if (enum_o2s^.o=lookup) then
  504. begin
  505. { direct lookup table }
  506. header:=Penum_typeinfo(typinfo);
  507. { calculate address of enum rtti body: add the actual size of the
  508. enum_rtti_header, and then align. Use an alignment of 1 (which
  509. does nothing) in case FPC_REQUIRES_PROPER_ALIGNMENT is not set
  510. to avoid the need for an if in this situation }
  511. {$ifdef VER3_0}
  512. body:=Penum_typedata(aligntoptr(pointer(header) + 2 * sizeof(byte) { kind, num_chars } + header^.num_chars));
  513. {$else VER3_0}
  514. body:=Penum_typedata(aligntoqword(pointer(header) + 2 * sizeof(byte) { kind, num_chars } + header^.num_chars));
  515. {$endif VER3_0}
  516. with body^ do
  517. begin
  518. { Bounds check for the ordinal value for this enum }
  519. if (ordinal<minvalue) or (ordinal>maxvalue) then
  520. exit;
  521. { make the ordinal index for lookup zero-based }
  522. dec(ordinal,minvalue);
  523. end;
  524. { temporarily disable range checking because of the access to the array[0..0]
  525. member of Tenum_ord_to_string_lookup }
  526. {$push}{$R-}
  527. res:=enum_o2s^.lookup_data[ordinal];
  528. {$pop}
  529. if (not assigned(res)) then
  530. exit;
  531. s:=res^;
  532. end
  533. else
  534. begin
  535. { The compiler did generate a sorted array of (ordvalue,Pstring) tuples }
  536. sorted_data:=@enum_o2s^.search_data;
  537. { Use a binary search to get the string }
  538. l:=0;
  539. { temporarily disable range checking because of the access to the array[0..0]
  540. member of Tenum_ord_to_string_search }
  541. {$push}{$R-}
  542. h:=enum_o2s^.num_entries-1;
  543. repeat
  544. m:=(l+h) div 2;
  545. if ordinal>sorted_data[m].value then
  546. l:=m+1
  547. else if ordinal<sorted_data[m].value then
  548. h:=m-1
  549. else
  550. break;
  551. if l>h then
  552. exit; { Ordinal value not found? Exit }
  553. until false;
  554. {$pop}
  555. s:=sorted_data[m].name^;
  556. end;
  557. { Pad the string with spaces if necessary }
  558. if (len>length(s)) then
  559. begin
  560. spaces:=len-length(s);
  561. for i:=1 to spaces do
  562. s[length(s)+i]:=' ';
  563. inc(byte(s[0]),spaces);
  564. end;
  565. fpc_shortstr_enum_intern:=0;
  566. end;
  567. {$endif with RTTI feature}
  568. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);[public,alias:'FPC_SHORTSTR_ENUM'];compilerproc;
  569. var
  570. res: longint;
  571. begin
  572. res:=fpc_shortstr_enum_intern(ordinal,len,typinfo,ord2strindex,s);
  573. if (res<>0) then
  574. runerror(107);
  575. end;
  576. { also define alias for internal use in the system unit }
  577. procedure fpc_shortstr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:shortstring);external name 'FPC_SHORTSTR_ENUM';
  578. {$endif FPC_SHORTSTR_ENUM_INTERN}
  579. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);[public,alias:'FPC_SHORTSTR_BOOL'];compilerproc;
  580. begin
  581. if b then
  582. s:='TRUE'
  583. else
  584. s:='FALSE';
  585. if length(s)<len then
  586. s:=space(len-length(s))+s;
  587. end;
  588. { also define alias for internal use in the system unit }
  589. procedure fpc_shortstr_bool(b : boolean;len:sizeint;out s:shortstring);external {$ifndef cpujvm}name 'FPC_SHORTSTR_BOOL'{$endif};
  590. procedure fpc_shortstr_currency({$ifdef cpujvm}constref{$endif} c : currency; len,f : SizeInt; out s : shortstring);[public,alias:'FPC_SHORTSTR_CURRENCY']; compilerproc;
  591. const
  592. MinLen = 8; { Minimal string length in scientific format }
  593. var
  594. buf : array[1..19] of AnsiChar;
  595. i,j,k,reslen,tlen,sign,r,point : ObjpasInt;
  596. ic : qword;
  597. begin
  598. fillchar(buf,length(buf),'0');
  599. { default value for length is -32767 }
  600. if len=-32767 then
  601. len:=25;
  602. if PInt64(@c)^ >= 0 then
  603. begin
  604. ic:=QWord(PInt64(@c)^);
  605. sign:=0;
  606. end
  607. else
  608. begin
  609. sign:=1;
  610. ic:=QWord(-PInt64(@c)^);
  611. end;
  612. { converting to integer string }
  613. tlen:=0;
  614. repeat
  615. Inc(tlen);
  616. buf[tlen]:=Chr(ic mod 10 + $30);
  617. ic:=ic div 10;
  618. until ic = 0;
  619. { calculating:
  620. reslen - length of result string,
  621. r - rounding or appending zeroes,
  622. point - place of decimal point }
  623. reslen:=tlen;
  624. if f <> 0 then
  625. Inc(reslen); { adding decimal point length }
  626. if f < 0 then
  627. begin
  628. { scientific format }
  629. Inc(reslen,5); { adding length of sign and exponent }
  630. if len < MinLen then
  631. len:=MinLen;
  632. r:=reslen-len;
  633. if reslen < len then
  634. reslen:=len;
  635. if r > 0 then
  636. begin
  637. reslen:=len;
  638. point:=tlen - r;
  639. end
  640. else
  641. point:=tlen;
  642. end
  643. else
  644. begin
  645. { fixed format }
  646. Inc(reslen, sign);
  647. { prepending fractional part with zeroes }
  648. while tlen < 5 do
  649. begin
  650. Inc(reslen);
  651. Inc(tlen);
  652. buf[tlen]:='0';
  653. end;
  654. { Currency have 4 digits in fractional part }
  655. r:=4 - f;
  656. point:=f;
  657. if point <> 0 then
  658. begin
  659. if point > 4 then
  660. point:=4;
  661. Inc(point);
  662. end;
  663. Dec(reslen,r);
  664. end;
  665. { rounding string if r > 0 }
  666. if r > 0 then
  667. begin
  668. k := 0;
  669. i := r+2;
  670. if i > tlen then
  671. i := tlen+1;
  672. if buf[i-2] >= '5' then
  673. begin
  674. if buf[i-1] < '9' then
  675. buf[i-1] := chr(ord(buf[i-1])+1)
  676. else
  677. begin
  678. buf[i-1] := '0';
  679. k := 1;
  680. end;
  681. end;
  682. If (k=1) and (buf[i-1]='0') then
  683. begin
  684. { 1.9996 rounded to two decimal digits after the decimal separator must result in
  685. 2.00, i.e. the rounding is propagated
  686. }
  687. while buf[i]='9' do
  688. begin
  689. buf[i]:='0';
  690. inc(i);
  691. end;
  692. buf[i]:=chr(Ord(buf[i])+1);
  693. { did we add another digit? This happens when rounding
  694. e.g. 99.9996 to two decimal digits after the decimal separator which should result in
  695. 100.00
  696. }
  697. if i>tlen then
  698. begin
  699. inc(reslen);
  700. inc(tlen);
  701. end;
  702. end;
  703. end;
  704. { preparing result string }
  705. if reslen<len then
  706. reslen:=len;
  707. if reslen>High(s) then
  708. begin
  709. if r < 0 then
  710. Inc(r, reslen - High(s));
  711. reslen:=High(s);
  712. end;
  713. SetLength(s,reslen);
  714. j:=reslen;
  715. if f<0 then
  716. begin
  717. { writing power of 10 part }
  718. if PInt64(@c)^ = 0 then
  719. k:=0
  720. else
  721. k:=tlen-5;
  722. if k >= 0 then
  723. s[j-2]:='+'
  724. else
  725. begin
  726. s[j-2]:='-';
  727. k:=-k;
  728. end;
  729. s[j]:=Chr(k mod 10 + $30);
  730. Dec(j);
  731. s[j]:=Chr(k div 10 + $30);
  732. Dec(j,2);
  733. s[j]:='E';
  734. Dec(j);
  735. end;
  736. { writing extra zeroes if r < 0 }
  737. while r < 0 do
  738. begin
  739. s[j]:='0';
  740. Dec(j);
  741. Inc(r);
  742. end;
  743. { writing digits and decimal point }
  744. for i:=r + 1 to tlen do
  745. begin
  746. Dec(point);
  747. if point = 0 then
  748. begin
  749. s[j]:='.';
  750. Dec(j);
  751. end;
  752. s[j]:=buf[i];
  753. Dec(j);
  754. end;
  755. { writing sign }
  756. if sign = 1 then
  757. begin
  758. s[j]:='-';
  759. Dec(j);
  760. end;
  761. { writing spaces }
  762. while j > 0 do
  763. begin
  764. s[j]:=' ';
  765. Dec(j);
  766. end;
  767. end;
  768. {
  769. Array Of AnsiChar Str() helpers
  770. }
  771. procedure fpc_chararray_sint(v : valsint;len : SizeInt;out a:array of AnsiChar);compilerproc;
  772. var
  773. ss : shortstring;
  774. maxlen : SizeInt;
  775. begin
  776. int_str(v,ss);
  777. if length(ss)<len then
  778. ss:=space(len-length(ss))+ss;
  779. if length(ss)<high(a)+1 then
  780. maxlen:=length(ss)
  781. else
  782. maxlen:=high(a)+1;
  783. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  784. end;
  785. procedure fpc_chararray_uint(v : valuint;len : SizeInt;out a : array of AnsiChar);compilerproc;
  786. var
  787. ss : shortstring;
  788. maxlen : SizeInt;
  789. begin
  790. int_str_unsigned(v,ss);
  791. if length(ss)<len then
  792. ss:=space(len-length(ss))+ss;
  793. if length(ss)<high(a)+1 then
  794. maxlen:=length(ss)
  795. else
  796. maxlen:=high(a)+1;
  797. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  798. end;
  799. {$ifndef CPU64}
  800. procedure fpc_chararray_qword(v : qword;len : SizeInt;out a : array of AnsiChar);compilerproc;
  801. {$ifdef EXCLUDE_COMPLEX_PROCS}
  802. begin
  803. runerror(219);
  804. end;
  805. {$else EXCLUDE_COMPLEX_PROCS}
  806. var
  807. ss : shortstring;
  808. maxlen : SizeInt;
  809. begin
  810. int_str_unsigned(v,ss);
  811. if length(ss)<len then
  812. ss:=space(len-length(ss))+ss;
  813. if length(ss)<high(a)+1 then
  814. maxlen:=length(ss)
  815. else
  816. maxlen:=high(a)+1;
  817. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  818. end;
  819. {$endif EXCLUDE_COMPLEX_PROCS}
  820. procedure fpc_chararray_int64(v : int64;len : SizeInt;out a : array of AnsiChar);compilerproc;
  821. {$ifdef EXCLUDE_COMPLEX_PROCS}
  822. begin
  823. runerror(219);
  824. end;
  825. {$else EXCLUDE_COMPLEX_PROCS}
  826. var
  827. ss : shortstring;
  828. maxlen : SizeInt;
  829. begin
  830. int_str(v,ss);
  831. if length(ss)<len then
  832. ss:=space(len-length(ss))+ss;
  833. if length(ss)<high(a)+1 then
  834. maxlen:=length(ss)
  835. else
  836. maxlen:=high(a)+1;
  837. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  838. end;
  839. {$endif EXCLUDE_COMPLEX_PROCS}
  840. {$endif CPU64}
  841. {$if defined(CPU16) or defined(CPU8)}
  842. procedure fpc_chararray_longword(v : longword;len : SizeInt;out a : array of AnsiChar);compilerproc;
  843. var
  844. ss : shortstring;
  845. maxlen : SizeInt;
  846. begin
  847. int_str_unsigned(v,ss);
  848. if length(ss)<len then
  849. ss:=space(len-length(ss))+ss;
  850. if length(ss)<high(a)+1 then
  851. maxlen:=length(ss)
  852. else
  853. maxlen:=high(a)+1;
  854. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  855. end;
  856. procedure fpc_chararray_longint(v : longint;len : SizeInt;out a : array of AnsiChar);compilerproc;
  857. var
  858. ss : shortstring;
  859. maxlen : SizeInt;
  860. begin
  861. int_str(v,ss);
  862. if length(ss)<len then
  863. ss:=space(len-length(ss))+ss;
  864. if length(ss)<high(a)+1 then
  865. maxlen:=length(ss)
  866. else
  867. maxlen:=high(a)+1;
  868. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  869. end;
  870. procedure fpc_chararray_word(v : word;len : SizeInt;out a : array of AnsiChar);compilerproc;
  871. var
  872. ss : shortstring;
  873. maxlen : SizeInt;
  874. begin
  875. int_str_unsigned(v,ss);
  876. if length(ss)<len then
  877. ss:=space(len-length(ss))+ss;
  878. if length(ss)<high(a)+1 then
  879. maxlen:=length(ss)
  880. else
  881. maxlen:=high(a)+1;
  882. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  883. end;
  884. procedure fpc_chararray_smallint(v : smallint;len : SizeInt;out a : array of AnsiChar);compilerproc;
  885. var
  886. ss : shortstring;
  887. maxlen : SizeInt;
  888. begin
  889. int_str(v,ss);
  890. if length(ss)<len then
  891. ss:=space(len-length(ss))+ss;
  892. if length(ss)<high(a)+1 then
  893. maxlen:=length(ss)
  894. else
  895. maxlen:=high(a)+1;
  896. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  897. end;
  898. {$endif CPU16 or CPU8}
  899. {$ifndef FPUNONE}
  900. procedure fpc_chararray_Float(d : ValReal;len,fr,rt : SizeInt;out a : array of AnsiChar);compilerproc;
  901. var
  902. ss : shortstring;
  903. maxlen : SizeInt;
  904. begin
  905. str_real(len,fr,d,treal_type(rt),ss);
  906. if length(ss)<high(a)+1 then
  907. maxlen:=length(ss)
  908. else
  909. maxlen:=high(a)+1;
  910. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  911. end;
  912. {$endif}
  913. {$ifndef FPC_STR_ENUM_INTERN}
  914. { currently, the avr code generator fails on this procedure, so we disable it,
  915. this is not a good solution but fixing compilation of this procedure for
  916. avr is hard, requires significant changes to the register allocator to take
  917. care of different register classes }
  918. procedure fpc_chararray_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out a : array of AnsiChar);compilerproc;
  919. var
  920. ss : shortstring;
  921. maxlen : SizeInt;
  922. begin
  923. {$ifdef EXCLUDE_COMPLEX_PROCS}
  924. runerror(219);
  925. {$else EXCLUDE_COMPLEX_PROCS}
  926. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  927. if length(ss)<high(a)+1 then
  928. maxlen:=length(ss)
  929. else
  930. maxlen:=high(a)+1;
  931. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  932. {$endif EXCLUDE_COMPLEX_PROCS}
  933. end;
  934. {$endif not FPC_STR_ENUM_INTERN}
  935. procedure fpc_chararray_bool(b : boolean;len:sizeint;out a : array of AnsiChar);compilerproc;
  936. var
  937. ss : shortstring;
  938. maxlen : SizeInt;
  939. begin
  940. fpc_shortstr_bool(b,len,ss);
  941. if length(ss)<high(a)+1 then
  942. maxlen:=length(ss)
  943. else
  944. maxlen:=high(a)+1;
  945. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  946. end;
  947. {$ifndef FPC_HAS_CHARARRAY_CURRENCY}
  948. {$define FPC_HAS_CHARARRAY_CURRENCY}
  949. procedure fpc_chararray_Currency(c : Currency;len,fr : SizeInt;out a : array of AnsiChar);compilerproc;
  950. {$ifdef EXCLUDE_COMPLEX_PROCS}
  951. begin
  952. runerror(217);
  953. end;
  954. {$else EXCLUDE_COMPLEX_PROCS}
  955. var
  956. ss : shortstring;
  957. maxlen : SizeInt;
  958. begin
  959. str(c:len:fr,ss);
  960. if length(ss)<high(a)+1 then
  961. maxlen:=length(ss)
  962. else
  963. maxlen:=high(a)+1;
  964. fpc_shortstr_chararray_intern_charmove(ss,a,maxlen);
  965. end;
  966. {$endif EXCLUDE_COMPLEX_PROCS}
  967. {$endif FPC_HAS_CHARARRAY_CURRENCY}
  968. {*****************************************************************************
  969. Val() Functions
  970. *****************************************************************************}
  971. Function InitVal(const s:shortstring;out negativ:boolean;out base:byte):ValSInt;
  972. var
  973. Code : SizeInt;
  974. begin
  975. code:=1;
  976. negativ:=false;
  977. base:=10;
  978. if length(s)=0 then
  979. begin
  980. InitVal:=code;
  981. Exit;
  982. end;
  983. {Skip Spaces and Tab}
  984. while (code<=length(s)) and (s[code] in [' ',#9]) do
  985. inc(code);
  986. {Sign}
  987. case s[code] of
  988. '-' : begin
  989. negativ:=true;
  990. inc(code);
  991. end;
  992. '+' : inc(code);
  993. end;
  994. {Base}
  995. if code<=length(s) then
  996. begin
  997. case s[code] of
  998. '$',
  999. 'X',
  1000. 'x' : begin
  1001. base:=16;
  1002. inc(code);
  1003. end;
  1004. '%' : begin
  1005. base:=2;
  1006. inc(code);
  1007. end;
  1008. '&' : begin
  1009. Base:=8;
  1010. inc(code);
  1011. end;
  1012. '0' : begin
  1013. if (code < length(s)) and (s[code+1] in ['x', 'X']) then
  1014. begin
  1015. inc(code, 2);
  1016. base := 16;
  1017. end;
  1018. end;
  1019. end;
  1020. end;
  1021. { strip leading zeros }
  1022. while ((code < length(s)) and (s[code] = '0')) do begin
  1023. inc(code);
  1024. end;
  1025. InitVal:=code;
  1026. end;
  1027. const
  1028. ValValueArray : array['0'..'f'] of byte = (0,1,2,3,4,5,6,7,8,9,$FF,$FF,$FF,$FF,$FF,$FF,$FF,10,11,12,13,14,15,
  1029. $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,
  1030. 10,11,12,13,14,15);
  1031. Function fpc_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; compilerproc;
  1032. var
  1033. temp, prev, maxPrevValue: ValUInt;
  1034. base,u : byte;
  1035. negative: boolean;
  1036. UnsignedUpperLimit: ValUInt;
  1037. begin
  1038. fpc_Val_SInt_ShortStr := 0;
  1039. Temp:=0;
  1040. Code:=InitVal(s,negative,base);
  1041. { avoid error about being uninitialized }
  1042. UnsignedUpperLimit := 0;
  1043. if (base=10) or negative then
  1044. begin //always limit to either Low(DestType) or High(DestType)
  1045. case DestSize of
  1046. 1: UnsignedUpperLimit := ValUInt(High(ShortInt))+Ord(negative);
  1047. 2: UnsignedUpperLimit := ValUInt(High(SmallInt))+Ord(negative);
  1048. 4: UnsignedUpperLimit := ValUInt(High(LongInt))+Ord(negative);
  1049. {$ifdef CPU64}
  1050. 8: UnsignedUpperLimit := ValUInt(High(Int64))+Ord(negative);
  1051. {$endif CPU64}
  1052. end;
  1053. end
  1054. else
  1055. begin //not decimal and not negative
  1056. case DestSize of
  1057. 1: UnsignedUpperLimit := High(Byte);
  1058. 2: UnsignedUpperLimit := High(Word);
  1059. 4: UnsignedUpperLimit := High(DWord);
  1060. {$ifdef CPU64}
  1061. 8: UnsignedUpperLimit := High(UInt64);
  1062. {$endif CPU64}
  1063. end;
  1064. end;
  1065. if Code>length(s) then
  1066. exit;
  1067. if (s[Code]=#0) then
  1068. begin
  1069. if (Code>1) and (s[Code-1]='0') then
  1070. Code:=0;
  1071. exit;
  1072. end;
  1073. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  1074. while Code<=Length(s) do
  1075. begin
  1076. u:=16;
  1077. case s[code] of
  1078. '0'..'f' : u:=ValValueArray[S[Code]];
  1079. #0 : break;
  1080. else
  1081. ;
  1082. end;
  1083. Prev := Temp;
  1084. Temp := Temp*ValUInt(base);
  1085. If (u >= base) or
  1086. (prev > maxPrevValue)
  1087. or ((Temp)>(UnsignedUpperLimit-u)) Then
  1088. Begin
  1089. fpc_Val_SInt_ShortStr := 0;
  1090. Exit
  1091. End;
  1092. Temp:=Temp+u;
  1093. inc(code);
  1094. end;
  1095. code := 0;
  1096. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  1097. If Negative Then
  1098. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  1099. If Not(Negative) and (base <> 10) Then
  1100. {sign extend the result to allow proper range checking}
  1101. Case DestSize of
  1102. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  1103. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  1104. {$ifdef cpu64}
  1105. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);
  1106. {$endif cpu64}
  1107. End;
  1108. end;
  1109. {$ifndef FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1110. {$define FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1111. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  1112. { we have to pass the DestSize parameter on (JM) }
  1113. Function int_Val_SInt_ShortStr(DestSize: SizeInt; Const S: ShortString; out Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  1114. {$endif FPC_HAS_INT_VAL_SINT_SHORTSTR}
  1115. 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;
  1116. var
  1117. base,u : byte;
  1118. negative : boolean;
  1119. UpperLimit: ValUInt;
  1120. begin
  1121. fpc_Val_UInt_Shortstr:=0;
  1122. Code:=InitVal(s,negative,base);
  1123. If Negative or (Code>length(s)) Then
  1124. begin
  1125. if Negative then Code:=Pos('-',S);
  1126. Exit;
  1127. end;
  1128. if (s[Code]=#0) then
  1129. begin
  1130. if (Code>1) and (s[Code-1]='0') then
  1131. Code:=0;
  1132. exit;
  1133. end;
  1134. {$ifndef VER3_2}
  1135. case DestSize of
  1136. 1: UpperLimit:=High(Byte);
  1137. 2: UpperLimit:=High(Word);
  1138. 4: UpperLimit:=High(DWord);
  1139. {$ifdef CPU64}
  1140. 8: UpperLimit:=High(QWord);
  1141. {$endif CPU64}
  1142. else
  1143. { avoid error about being uninitialized }
  1144. UpperLimit:=0;
  1145. end;
  1146. {$else VER3_2}
  1147. UpperLimit:=High(ValUInt); //this preserves 3.2 (and earlier) behaviour
  1148. {$ENDIF}
  1149. while Code<=Length(s) do
  1150. begin
  1151. u:=16;
  1152. case s[code] of
  1153. '0'..'f' : u:=ValValueArray[S[Code]];
  1154. #0 : break;
  1155. else
  1156. ;
  1157. end;
  1158. If (u>=base) or
  1159. (ValUInt(UpperLimit-u) div ValUInt(Base)<fpc_val_uint_shortstr) then
  1160. begin
  1161. fpc_Val_UInt_Shortstr:=0;
  1162. exit;
  1163. end;
  1164. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  1165. inc(code);
  1166. end;
  1167. code := 0;
  1168. {$ifndef VER3_2}
  1169. case DestSize of
  1170. 1: fpc_Val_UInt_Shortstr:=Byte(fpc_Val_UInt_Shortstr);
  1171. 2: fpc_Val_UInt_Shortstr:=Word(fpc_Val_UInt_Shortstr);
  1172. 4: fpc_Val_UInt_Shortstr:=DWord(fpc_Val_UInt_Shortstr);
  1173. //8: no typecast needed for QWord
  1174. end;
  1175. {$ENDIF}
  1176. end;
  1177. {$ifndef CPU64}
  1178. Function fpc_val_int64_shortstr(Const S: ShortString; out Code: ValSInt): Int64; [public, alias:'FPC_VAL_INT64_SHORTSTR']; compilerproc;
  1179. var u : sizeuint;
  1180. temp, prev, maxprevvalue, maxnewvalue : qword;
  1181. base : byte;
  1182. negative : boolean;
  1183. const maxint64=qword($7fffffffffffffff);
  1184. minint64_unsigned=qword($8000000000000000);
  1185. maxqword=qword($ffffffffffffffff);
  1186. begin
  1187. {$ifdef EXCLUDE_COMPLEX_PROCS}
  1188. runerror(219);
  1189. {$else EXCLUDE_COMPLEX_PROCS}
  1190. fpc_val_int64_shortstr := 0;
  1191. Temp:=0;
  1192. Code:=InitVal(s,negative,base);
  1193. if Code>length(s) then
  1194. exit;
  1195. if (s[Code]=#0) then
  1196. begin
  1197. if (Code>1) and (s[Code-1]='0') then
  1198. Code:=0;
  1199. exit;
  1200. end;
  1201. maxprevvalue := maxqword div base;
  1202. if (base = 10) then
  1203. maxnewvalue := maxint64 + ord(negative)
  1204. else
  1205. maxnewvalue := maxqword;
  1206. while Code<=Length(s) do
  1207. begin
  1208. u:=16;
  1209. case s[code] of
  1210. '0'..'f' : u:=ValValueArray[S[Code]];
  1211. #0 : break;
  1212. else
  1213. ;
  1214. end;
  1215. Prev:=Temp;
  1216. Temp:=Temp*qword(base);
  1217. If (u >= base) or
  1218. (qword(maxnewvalue-u) < temp) or
  1219. (prev > maxprevvalue) or
  1220. ((base<>10) and (negative) and ((Temp+u)>minint64_unsigned)) Then
  1221. Begin
  1222. fpc_val_int64_shortstr := 0;
  1223. Exit
  1224. End;
  1225. Temp:=Temp+u;
  1226. inc(code);
  1227. end;
  1228. code:=0;
  1229. fpc_val_int64_shortstr:=int64(Temp);
  1230. If Negative Then
  1231. fpc_val_int64_shortstr:=-fpc_val_int64_shortstr;
  1232. {$endif EXCLUDE_COMPLEX_PROCS}
  1233. end;
  1234. Function fpc_val_qword_shortstr(Const S: ShortString; out Code: ValSInt): QWord; [public, alias:'FPC_VAL_QWORD_SHORTSTR']; compilerproc;
  1235. var u : sizeuint;
  1236. base : byte;
  1237. negative : boolean;
  1238. const maxqword=qword($ffffffffffffffff);
  1239. begin
  1240. fpc_val_qword_shortstr:=0;
  1241. Code:=InitVal(s,negative,base);
  1242. If Negative or (Code>length(s)) Then
  1243. begin
  1244. if Negative then Code:=Pos('-',S);
  1245. Exit;
  1246. end;
  1247. if (s[Code]=#0) then
  1248. begin
  1249. if (Code>1) and (s[Code-1]='0') then
  1250. Code:=0;
  1251. exit;
  1252. end;
  1253. while Code<=Length(s) do
  1254. begin
  1255. u:=16;
  1256. case s[code] of
  1257. '0'..'f' : u:=ValValueArray[S[Code]];
  1258. #0 : break;
  1259. else
  1260. ;
  1261. end;
  1262. If (u>=base) or
  1263. ((QWord(maxqword-u) div QWord(base))<fpc_val_qword_shortstr) then
  1264. Begin
  1265. fpc_val_qword_shortstr := 0;
  1266. Exit
  1267. End;
  1268. fpc_val_qword_shortstr:=fpc_val_qword_shortstr*QWord(base) + u;
  1269. inc(code);
  1270. end;
  1271. code := 0;
  1272. end;
  1273. {$endif CPU64}
  1274. {$if defined(CPU16) or defined(CPU8)}
  1275. Function fpc_val_longint_shortstr(Const S: ShortString; out Code: ValSInt): LongInt; [public, alias:'FPC_VAL_LONGINT_SHORTSTR']; compilerproc;
  1276. var u, temp, prev, maxprevvalue, maxnewvalue : longword;
  1277. base : byte;
  1278. negative : boolean;
  1279. const maxlongint=longword($7fffffff);
  1280. maxlongword=longword($ffffffff);
  1281. begin
  1282. fpc_val_longint_shortstr := 0;
  1283. Temp:=0;
  1284. Code:=InitVal(s,negative,base);
  1285. if Code>length(s) then
  1286. exit;
  1287. if (s[Code]=#0) then
  1288. begin
  1289. if (Code>1) and (s[Code-1]='0') then
  1290. Code:=0;
  1291. exit;
  1292. end;
  1293. maxprevvalue := maxlongword div base;
  1294. if (base = 10) then
  1295. maxnewvalue := maxlongint + ord(negative)
  1296. else
  1297. maxnewvalue := maxlongword;
  1298. while Code<=Length(s) do
  1299. begin
  1300. u:=16;
  1301. case s[code] of
  1302. '0'..'f' : u:=ValValueArray[S[Code]];
  1303. #0 : break;
  1304. else
  1305. ;
  1306. end;
  1307. Prev:=Temp;
  1308. Temp:=Temp*longword(base);
  1309. If (u >= base) or
  1310. (longword(maxnewvalue-u) < temp) or
  1311. (prev > maxprevvalue) Then
  1312. Begin
  1313. fpc_val_longint_shortstr := 0;
  1314. Exit;
  1315. End;
  1316. Temp:=Temp+u;
  1317. inc(code);
  1318. end;
  1319. code:=0;
  1320. fpc_val_longint_shortstr:=longint(Temp);
  1321. If Negative Then
  1322. fpc_val_longint_shortstr:=-fpc_val_longint_shortstr;
  1323. end;
  1324. Function fpc_val_longword_shortstr(Const S: ShortString; out Code: ValSInt): LongWord; [public, alias:'FPC_VAL_LONGWORD_SHORTSTR']; compilerproc;
  1325. var u, prev: LongWord;
  1326. base : byte;
  1327. negative : boolean;
  1328. const UpperLimit=High(longword);
  1329. begin
  1330. fpc_val_longword_shortstr:=0;
  1331. Code:=InitVal(s,negative,base);
  1332. If Negative or (Code>length(s)) Then
  1333. Exit;
  1334. if (s[Code]=#0) then
  1335. begin
  1336. if (Code>1) and (s[Code-1]='0') then
  1337. Code:=0;
  1338. exit;
  1339. end;
  1340. while Code<=Length(s) do
  1341. begin
  1342. u:=16;
  1343. case s[code] of
  1344. '0'..'f' : u:=ValValueArray[S[Code]];
  1345. #0 : break;
  1346. else
  1347. ;
  1348. end;
  1349. If (u>=base) or
  1350. (LongWord(UpperLimit-u) div LongWord(Base)<fpc_val_longword_shortstr) then
  1351. begin
  1352. fpc_val_longword_shortstr:=0;
  1353. exit;
  1354. end;
  1355. fpc_val_longword_shortstr:=fpc_val_longword_shortstr*base + u;
  1356. inc(code);
  1357. end;
  1358. code := 0;
  1359. end;
  1360. Function fpc_val_smallint_shortstr(Const S: ShortString; out Code: ValSInt): SmallInt; [public, alias:'FPC_VAL_SMALLINT_SHORTSTR']; compilerproc;
  1361. var u, temp, prev, maxprevvalue : word;
  1362. base : byte;
  1363. negative : boolean;
  1364. UnsignedUpperLimit: ValUInt;
  1365. begin
  1366. fpc_val_smallint_shortstr := 0;
  1367. Temp:=0;
  1368. Code:=InitVal(s,negative,base);
  1369. if (base=10) or negative then
  1370. UnsignedUpperLimit := Word(High(SmallInt))+Ord(negative)
  1371. else
  1372. UnsignedUpperLimit := High(Word);
  1373. if Code>length(s) then
  1374. exit;
  1375. if (s[Code]=#0) then
  1376. begin
  1377. if (Code>1) and (s[Code-1]='0') then
  1378. Code:=0;
  1379. exit;
  1380. end;
  1381. maxprevvalue := High(Word) div base;
  1382. while Code<=Length(s) do
  1383. begin
  1384. u:=16;
  1385. case s[code] of
  1386. '0'..'f' : u:=ValValueArray[S[Code]];
  1387. #0 : break;
  1388. else
  1389. ;
  1390. end;
  1391. Prev:=Temp;
  1392. Temp:=Temp*longword(base);
  1393. If (u >= base) or
  1394. (prev > maxPrevValue) or
  1395. ((Temp)>(UnsignedUpperLimit-u)) Then
  1396. Begin
  1397. fpc_val_smallint_shortstr := 0;
  1398. Exit
  1399. End;
  1400. Temp:=Temp+u;
  1401. inc(code);
  1402. end;
  1403. code:=0;
  1404. fpc_val_smallint_shortstr:=SmallInt(Temp);
  1405. If Negative Then
  1406. fpc_val_smallint_shortstr:=-fpc_val_smallint_shortstr;
  1407. end;
  1408. Function fpc_val_word_shortstr(Const S: ShortString; out Code: ValSInt): Word; [public, alias:'FPC_VAL_WORD_SHORTSTR']; compilerproc;
  1409. var u, prev: word;
  1410. base : byte;
  1411. negative : boolean;
  1412. const UpperLimit=High(Word); //this preserves 3.2 (and earlier) behaviour
  1413. begin
  1414. fpc_val_word_shortstr:=0;
  1415. Code:=InitVal(s,negative,base);
  1416. If Negative or (Code>length(s)) Then
  1417. begin
  1418. if Negative then Code:=Pos('-',S);
  1419. Exit;
  1420. end;
  1421. if (s[Code]=#0) then
  1422. begin
  1423. if (Code>1) and (s[Code-1]='0') then
  1424. Code:=0;
  1425. exit;
  1426. end;
  1427. while Code<=Length(s) do
  1428. begin
  1429. u:=16;
  1430. case s[code] of
  1431. '0'..'f' : u:=ValValueArray[S[Code]];
  1432. #0 : break;
  1433. else
  1434. ;
  1435. end;
  1436. If (u>=base) or
  1437. (Word(UpperLimit-u) div Word(Base)<fpc_val_word_shortstr) then
  1438. begin
  1439. fpc_val_word_shortstr:=0;
  1440. exit;
  1441. end;
  1442. fpc_val_word_shortstr:=fpc_val_word_shortstr*base + u;
  1443. inc(code);
  1444. end;
  1445. code := 0;
  1446. end;
  1447. {$endif CPU16 or CPU8}
  1448. {$ifndef FPUNONE}
  1449. Function fpc_Val_Real_ShortStr(const s : shortstring; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; compilerproc;
  1450. begin
  1451. fpc_Val_Real_ShortStr := val_real( s, code );
  1452. end;
  1453. {$endif FPUNONE}
  1454. {$ifndef FPC_STR_ENUM_INTERN}
  1455. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_SHORTSTR']; compilerproc;
  1456. type Psorted_array=^Tsorted_array;
  1457. Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1458. o:longint;
  1459. s:Pstring;
  1460. end;
  1461. Pstring_to_ord=^Tstring_to_ord;
  1462. Tstring_to_ord={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
  1463. count:longint;
  1464. data:array[0..0] of Tsorted_array;
  1465. end;
  1466. var l,r,l2,r2,m,sp,isp:SizeInt;
  1467. c:char;
  1468. begin
  1469. {Val for numbers accepts spaces at the start, so lets do the same
  1470. for enums. Skip spaces at the start of the string.}
  1471. sp:=1;
  1472. while (sp<=length(s)) and (s[sp]=' ') do
  1473. inc(sp);
  1474. { Let input be “abd” and sorted names be: _hm a aa ab aba abb abc abd ac ad b c
  1475. Start: L ┘R (R points PAST the last item in the range.)
  1476. After iteration 0 (“a” analyzed): L ┘R
  1477. After iteration 1 (“ab” analyzed): L ┘R
  1478. After iteration 2 (“abd” analyzed): L ┘R }
  1479. l:=0;
  1480. r:=Pstring_to_ord(str2ordindex)^.count;
  1481. dec(sp); { sp/isp are incremented at the beginning of the loop so that 'continue's advance sp/isp. }
  1482. isp:=0; { isp is the position without spaces. }
  1483. repeat
  1484. inc(sp);
  1485. if sp>length(s) then
  1486. break;
  1487. inc(isp);
  1488. c:=UpCase(s[sp]);
  1489. { Among all strings beginning with, say, ‘ab’, the ‘ab’ itself will be the first.
  1490. So after this check, “isp ≤ length(any string in the range)” is guaranteed. }
  1491. if isp>length(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[l].s^) then
  1492. begin
  1493. inc(l);
  1494. if l=r then
  1495. break;
  1496. end;
  1497. 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). }
  1498. begin
  1499. if l+1=r then { Shortcut: the only string left (enums often have different suffixes). }
  1500. continue;
  1501. end
  1502. else
  1503. begin
  1504. r2:=r; { Search for new L. }
  1505. repeat
  1506. m:=SizeUint(l+r2) div 2;
  1507. if UpCase(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[m].s^[isp])<c then
  1508. l:=m+1
  1509. else
  1510. r2:=m;
  1511. until l=r2;
  1512. if l=r then
  1513. break;
  1514. end;
  1515. if UpCase(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[r-1].s^[isp])=c then { Shortcut: R−1 may be already correct. }
  1516. continue;
  1517. l2:=l; { Search for new R. }
  1518. repeat
  1519. m:=SizeUint(l2+r) div 2;
  1520. if UpCase(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[m].s^[isp])<=c then
  1521. l2:=m+1
  1522. else
  1523. r:=m;
  1524. until l2=r;
  1525. if l=r then { Better not to make it the loop condition, or ‘continue’s may jump to it instead of the beginning. }
  1526. break;
  1527. until false;
  1528. if (l<r) and (isp=length(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[l].s^)) then
  1529. begin
  1530. code:=0;
  1531. exit(Psorted_array(Pstring_to_ord(str2ordindex)^.data)[l].o);
  1532. end;
  1533. code:=sp;
  1534. result:=-1; { Formally undefined, but −1 is very likely the invalid value prone to crashing, which is better than accidentally working. }
  1535. end;
  1536. {Redeclare fpc_val_enum_shortstr for internal use in the system unit.}
  1537. function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code:valsint):longint;external name 'FPC_VAL_ENUM_SHORTSTR';
  1538. {$endif FPC_STR_ENUM_INTERN}
  1539. function fpc_Val_Currency_ShortStr(const s : shortstring; out Code : ValSInt): currency; [public, alias:'FPC_VAL_CURRENCY_SHORTSTR']; compilerproc;
  1540. {$ifdef EXCLUDE_COMPLEX_PROCS}
  1541. begin
  1542. runerror(217);
  1543. end;
  1544. {$else EXCLUDE_COMPLEX_PROCS}
  1545. const
  1546. MinInt64 : Int64 =-$8000000000000000;
  1547. MinInt64Edge : Int64 = (-$8000000000000000 + 10) div 10;
  1548. var
  1549. { to enable taking the address on the JVM target }
  1550. res : array[0..0] of Int64;
  1551. i,j,power,sign,len : longint;
  1552. FracOverflow : boolean;
  1553. begin
  1554. fpc_Val_Currency_ShortStr:=0;
  1555. res[0]:=0;
  1556. len:=Length(s);
  1557. Code:=1;
  1558. sign:=-1;
  1559. power:=0;
  1560. while True do
  1561. if Code > len then
  1562. exit
  1563. else
  1564. if s[Code] in [' ', #9] then
  1565. Inc(Code)
  1566. else
  1567. break;
  1568. { Read sign }
  1569. case s[Code] of
  1570. '+' : begin
  1571. Inc(Code);
  1572. end;
  1573. '-' : begin
  1574. sign:=+1;
  1575. Inc(Code);
  1576. end;
  1577. end;
  1578. { Read digits }
  1579. FracOverflow:=False;
  1580. i:=0;
  1581. while Code <= len do
  1582. begin
  1583. case s[Code] of
  1584. '0'..'9':
  1585. begin
  1586. j:=Ord(s[code])-Ord('0');
  1587. { check overflow }
  1588. if (res[0] >= MinInt64Edge) or (res[0] >= (MinInt64 + j) div 10) then
  1589. begin
  1590. res[0]:=res[0]*10 - j;
  1591. Inc(i);
  1592. end
  1593. else
  1594. if power = 0 then
  1595. { exit if integer part overflow }
  1596. exit
  1597. else
  1598. begin
  1599. if not FracOverflow and (j >= 5) and (res[0] > MinInt64) then
  1600. { round if first digit of fractional part overflow }
  1601. Dec(res[0]);
  1602. FracOverflow:=True;
  1603. end;
  1604. end;
  1605. '.':
  1606. begin
  1607. if power = 0 then
  1608. begin
  1609. power:=1;
  1610. i:=0;
  1611. end
  1612. else
  1613. exit;
  1614. end;
  1615. else
  1616. break;
  1617. end;
  1618. Inc(Code);
  1619. end;
  1620. if (i = 0) and (power = 0) then
  1621. exit;
  1622. if power <> 0 then
  1623. power:=i;
  1624. power:=4 - power;
  1625. { Exponent? }
  1626. if Code <= len then
  1627. if s[Code] in ['E', 'e'] then
  1628. begin
  1629. Inc(Code);
  1630. if Code > len then
  1631. exit;
  1632. i:=1;
  1633. case s[Code] of
  1634. '+':
  1635. Inc(Code);
  1636. '-':
  1637. begin
  1638. i:=-1;
  1639. Inc(Code);
  1640. end;
  1641. end;
  1642. { read exponent }
  1643. j:=0;
  1644. while Code <= len do
  1645. if s[Code] in ['0'..'9'] then
  1646. begin
  1647. if j > 4951 then
  1648. exit;
  1649. j:=j*10 + (Ord(s[code])-Ord('0'));
  1650. Inc(Code);
  1651. end
  1652. else
  1653. exit;
  1654. power:=power + j*i;
  1655. end
  1656. else
  1657. exit;
  1658. if power > 0 then
  1659. begin
  1660. for i:=1 to power do
  1661. if res[0] >= MinInt64 div 10 then
  1662. res[0]:=res[0]*10
  1663. else
  1664. exit;
  1665. end
  1666. else
  1667. for i:=1 to -power do
  1668. begin
  1669. if res[0] >= MinInt64 + 5 then
  1670. Dec(res[0], 5);
  1671. res[0]:=res[0] div 10;
  1672. end;
  1673. if sign <> 1 then
  1674. if res[0] > MinInt64 then
  1675. res[0]:=res[0]*sign
  1676. else
  1677. exit;
  1678. fpc_Val_Currency_ShortStr:=PCurrency(@res[0])^;
  1679. Code:=0;
  1680. end;
  1681. {$endif EXCLUDE_COMPLEX_PROCS}
  1682. {$ifndef FPC_HAS_SETSTRING_SHORTSTR}
  1683. {$define FPC_HAS_SETSTRING_SHORTSTR}
  1684. Procedure {$ifdef FPC_HAS_CPSTRING}fpc_setstring_shortstr{$else}SetString{$endif}(Out S : Shortstring; Buf : PAnsiChar; Len : SizeInt); {$ifdef FPC_HAS_CPSTRING} compilerproc; {$endif FPC_HAS_CPSTRING}
  1685. begin
  1686. If Len > High(S) then
  1687. Len := High(S);
  1688. SetLength(S,Len);
  1689. If Buf<>Nil then
  1690. begin
  1691. Move (Buf[0],S[1],Len);
  1692. end;
  1693. end;
  1694. {$endif FPC_HAS_SETSTRING_SHORTSTR}
  1695. {$ifndef FPC_HAS_COMPARETEXT_SHORTSTR}
  1696. {$define FPC_HAS_COMPARETEXT_SHORTSTR}
  1697. function ShortCompareText(const S1, S2: shortstring): SizeInt;
  1698. var
  1699. c1, c2: Byte;
  1700. i: SizeInt;
  1701. L1, L2, Count: SizeInt;
  1702. P1, P2: PAnsiChar;
  1703. begin
  1704. L1 := Length(S1);
  1705. L2 := Length(S2);
  1706. if L1 > L2 then
  1707. Count := L2
  1708. else
  1709. Count := L1;
  1710. i := 0;
  1711. P1 := @S1[1];
  1712. P2 := @S2[1];
  1713. while i < count do
  1714. begin
  1715. c1 := byte(p1^);
  1716. c2 := byte(p2^);
  1717. if c1 <> c2 then
  1718. begin
  1719. if c1 in [97..122] then
  1720. Dec(c1, 32);
  1721. if c2 in [97..122] then
  1722. Dec(c2, 32);
  1723. if c1 <> c2 then
  1724. Break;
  1725. end;
  1726. Inc(P1); Inc(P2); Inc(I);
  1727. end;
  1728. if i < count then
  1729. ShortCompareText := c1 - c2
  1730. else
  1731. ShortCompareText := L1 - L2;
  1732. end;
  1733. {$endif FPC_HAS_COMPARETEXT_SHORTSTR}