astrings.inc 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Michael Van Canneyt,
  4. member of the Free Pascal development team.
  5. This file implements AnsiStrings for FPC
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { This will release some functions for special shortstring support }
  13. { define EXTRAANSISHORT}
  14. {$ifndef FPC_ANSISTRING_TYPE_DEFINED}
  15. {$define FPC_ANSISTRING_TYPE_DEFINED}
  16. {
  17. This file contains the implementation of the AnsiString type,
  18. and all things that are needed for it.
  19. AnsiString is defined as a 'silent' pansichar :
  20. a pansichar that points to (S= SizeOf(SizeInt), R= (if CPU64 then SizeOf(Longint) else SizeOf(SizeInt))):
  21. @-S-R-4 : Code page indicator.
  22. @-S-R-2 : Character size (2 bytes)
  23. @-S-R : Reference count (R bytes)
  24. @-S : SizeInt for size;
  25. @ : String + Terminating #0;
  26. PAnsiChar(Ansistring) is a valid typecast.
  27. So AS[i] is converted to the address @AS+i-1.
  28. Constants should be assigned a reference count of -1
  29. Meaning that they can't be disposed of.
  30. }
  31. Type
  32. PAnsiRec = ^TAnsiRec;
  33. TAnsiRec = Record
  34. CodePage : TSystemCodePage;
  35. ElementSize : Word;
  36. {$if not defined(VER3_2)}
  37. {$ifdef CPU64}
  38. Ref : Longint;
  39. {$else}
  40. Ref : SizeInt;
  41. {$endif}
  42. {$else}
  43. {$ifdef CPU64}
  44. { align fields }
  45. Dummy : DWord;
  46. {$endif CPU64}
  47. Ref : SizeInt;
  48. {$endif}
  49. Len : SizeInt;
  50. end;
  51. Const
  52. AnsiFirstOff = SizeOf(TAnsiRec);
  53. {$endif FPC_ANSISTRING_TYPE_DEFINED}
  54. {****************************************************************************
  55. Internal functions, not in interface.
  56. ****************************************************************************}
  57. {$ifndef FPC_HAS_TRANSLATEPLACEHOLDERCP}
  58. {$define FPC_HAS_TRANSLATEPLACEHOLDERCP}
  59. function TranslatePlaceholderCP(cp: TSystemCodePage): TSystemCodePage; {$ifdef SYSTEMINLINE}inline;{$endif}
  60. begin
  61. TranslatePlaceholderCP:=cp;
  62. case cp of
  63. CP_OEMCP,
  64. CP_ACP:
  65. TranslatePlaceholderCP:=DefaultSystemCodePage;
  66. end;
  67. end;
  68. {$endif FPC_HAS_TRANSLATEPLACEHOLDERCP}
  69. {$ifndef FPC_HAS_PCHAR_ANSISTR_INTERN_CHARMOVE}
  70. {$define FPC_HAS_PCHAR_ANSISTR_INTERN_CHARMOVE}
  71. procedure fpc_pchar_ansistr_intern_charmove(const src: pansichar; const srcindex: sizeint; var dst: rawbytestring; const dstindex, len: sizeint); rtlproc;{$ifdef SYSTEMINLINE}inline;{$endif}
  72. begin
  73. move(src[srcindex],pbyte(pointer(dst))[dstindex],len);
  74. end;
  75. {$endif FPC_HAS_PCHAR_ANSISTR_INTERN_CHARMOVE}
  76. {$ifndef FPC_HAS_PCHAR_PCHAR_INTERN_CHARMOVE}
  77. {$define FPC_HAS_PCHAR_PCHAR_INTERN_CHARMOVE}
  78. procedure fpc_pchar_pchar_intern_charmove(const src: pansichar; const srcindex: sizeint; const dst: pansichar; const dstindex, len: sizeint); rtlproc; {$ifdef SYSTEMINLINE}inline;{$endif}
  79. begin
  80. move(src[srcindex],dst[dstindex],len);
  81. end;
  82. {$endif FPC_HAS_PCHAR_PCHAR_INTERN_CHARMOVE}
  83. {$ifndef FPC_HAS_SHORTSTR_ANSISTR_INTERN_CHARMOVE}
  84. {$define FPC_HAS_SHORTSTR_ANSISTR_INTERN_CHARMOVE}
  85. procedure fpc_shortstr_ansistr_intern_charmove(const src: shortstring; const srcindex: sizeint; var dst: rawbytestring; const dstindex, len: sizeint); rtlproc; {$ifdef SYSTEMINLINE}inline;{$endif}
  86. begin
  87. move(src[srcindex],pbyte(pointer(dst))[dstindex],len);
  88. end;
  89. {$endif FPC_HAS_SHORTSTR_ANSISTR_INTERN_CHARMOVE}
  90. {$ifndef FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  91. {$define FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  92. Procedure fpc_ansistr_decr_ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DECR_REF']; compilerproc;
  93. {
  94. Decreases the ReferenceCount of a non constant ansistring;
  95. If the reference count is zero, deallocate the string;
  96. }
  97. Var
  98. p: pointer;
  99. Begin
  100. p:=S;
  101. If p=Nil then
  102. exit;
  103. s:=nil;
  104. If (PAnsiRec(p-AnsiFirstOff)^.ref>0) and { ref = -1 is constant string. }
  105. ((PAnsiRec(p-AnsiFirstOff)^.ref=1) { Shortcut declocked on ref = 1. }
  106. or declocked(PAnsiRec(p-AnsiFirstOff)^.ref)) then
  107. FreeMem(p-AnsiFirstOff);
  108. end;
  109. {$endif FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  110. { also define alias for internal use in the system unit }
  111. Procedure fpc_ansistr_decr_ref (Var S : Pointer); [external name 'FPC_ANSISTR_DECR_REF'];
  112. {$ifndef FPC_SYSTEM_HAS_ANSISTR_INCR_REF}
  113. {$define FPC_SYSTEM_HAS_ANSISTR_INCR_REF}
  114. Procedure fpc_AnsiStr_Incr_Ref (S : Pointer); [Public,Alias:'FPC_ANSISTR_INCR_REF']; compilerproc; inline;
  115. Begin
  116. If S=Nil then
  117. exit;
  118. { Let's be paranoid : Constant string ??}
  119. If PAnsiRec(S-AnsiFirstOff)^.Ref<0 then exit;
  120. inclocked(PAnsiRec(S-AnsiFirstOff)^.Ref);
  121. end;
  122. {$endif FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  123. { also define alias which can be used inside the system unit }
  124. Procedure fpc_AnsiStr_Incr_Ref (S : Pointer); [external name 'FPC_ANSISTR_INCR_REF'];
  125. {$ifndef FPC_HAS_ANSISTR_ASSIGN}
  126. {$define FPC_HAS_ANSISTR_ASSIGN}
  127. Procedure fpc_AnsiStr_Assign (Var DestS : Pointer;S2 : Pointer);[Public,Alias:'FPC_ANSISTR_ASSIGN']; compilerproc;
  128. {
  129. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  130. }
  131. begin
  132. if DestS=S2 then
  133. exit;
  134. If S2<>nil then
  135. If PAnsiRec(S2-AnsiFirstOff)^.Ref>0 then
  136. inclocked(PAnsiRec(S2-AnsiFirstOff)^.Ref);
  137. { Decrease the reference count on the old S1 }
  138. fpc_ansistr_decr_ref (DestS);
  139. { And finally, have DestS pointing to S2 (or its copy) }
  140. DestS:=S2;
  141. end;
  142. {$endif FPC_HAS_ANSISTR_ASSIGN}
  143. { alias for internal use }
  144. Procedure fpc_AnsiStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_ANSISTR_ASSIGN'];
  145. {$ifndef FPC_HAS_ANSISTR_CONCAT_COMPLEX}
  146. {$define FPC_HAS_ANSISTR_CONCAT_COMPLEX}
  147. { keeps implicit try..finally block out from primary control flow }
  148. procedure ansistr_concat_complex(var DestS: RawByteString; const S1,S2: RawByteString; cp: TSystemCodePage);
  149. var
  150. U: UnicodeString;
  151. begin
  152. U:=UnicodeString(S1)+UnicodeString(S2);
  153. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(U)),DestS,cp,Length(U));
  154. end;
  155. {$endif FPC_HAS_ANSISTR_CONCAT_COMPLEX}
  156. {$ifndef FPC_HAS_ANSISTR_CONCAT}
  157. {$define FPC_HAS_ANSISTR_CONCAT}
  158. procedure fpc_AnsiStr_Concat (var DestS:RawByteString;const S1,S2 : RawByteString;cp : TSystemCodePage); compilerproc;
  159. Var
  160. S1Len, S2Len: SizeInt;
  161. S1CP, S2CP, DestCP: TSystemCodePage;
  162. OldDestP, NewDestP, RealDestP, Src : Pointer;
  163. begin
  164. DestCP:=cp;
  165. if DestCp=CP_NONE then
  166. DestCP:=DefaultSystemCodePage;
  167. DestCP:=TranslatePlaceholderCP(DestCP);
  168. { if codepages are different then concat using unicodestring,
  169. but avoid conversions if either addend is empty (StringCodePage will return
  170. DefaultSystemCodePage in that case, which may differ from other addend/dest) }
  171. S1CP:=DestCP;
  172. if Length(S1)<>0 then
  173. S1CP:=TranslatePlaceholderCP(StringCodePage(S1));
  174. S2CP:=S1CP; { So if S2 is empty, S2CP = S1CP. }
  175. if Length(S2)<>0 then
  176. S2CP:=TranslatePlaceholderCP(StringCodePage(S2));
  177. { if the result is rawbytestring and both strings have the same code page,
  178. keep that code page or keep the code page if the other string is empty }
  179. if cp=CP_NONE then
  180. if S1CP=S2CP then { Includes the case of empty S2. }
  181. DestCP:=S1CP
  182. else if Length(S1)=0 then
  183. begin
  184. DestCP:=S2CP;
  185. S1CP:=S2CP;
  186. end;
  187. if (S1CP<>DestCP) or (S2CP<>DestCP) then
  188. begin
  189. ansistr_concat_complex(DestS,S1,S2,DestCP);
  190. exit;
  191. end;
  192. { only assign if s1 or s2 is empty }
  193. if (Length(S1)=0) then
  194. begin
  195. DestS:=s2;
  196. exit;
  197. end;
  198. if (Length(S2)=0) then
  199. begin
  200. DestS:=s1;
  201. exit;
  202. end;
  203. S1Len:=PAnsiRec(Pointer(S1)-AnsiFirstOff)^.Len;
  204. S2Len:=PAnsiRec(Pointer(S2)-AnsiFirstOff)^.Len;
  205. OldDestP:=Pointer(DestS);
  206. { Reallocate when possible; in the hope this will reuse the chunk more often than do a redundant copy. }
  207. if Assigned(OldDestP) and (PAnsiRec(OldDestP-AnsiFirstOff)^.Ref=1) then
  208. begin
  209. RealDestP:=OldDestP-AnsiFirstOff;
  210. NewDestP:=ReallocMem(RealDestP,AnsiFirstOff+1+S1Len+S2Len)+AnsiFirstOff;
  211. { Copy S2 first, as in the case of OldDestP = Pointer(S2) it must be copied first and in other cases the order does not matter. }
  212. Src:=Pointer(S2);
  213. if Src=OldDestP then
  214. Src:=NewDestP;
  215. Move(Src^,PAnsiChar(NewDestP)[S1Len],S2Len);
  216. if OldDestP<>Pointer(S1) then { Not an append, need to copy S1? }
  217. Move(Pointer(S1)^,NewDestP^,S1Len);
  218. end
  219. else
  220. begin
  221. NewDestP:=GetMem(S1Len+S2Len+(AnsiFirstOff+1))+AnsiFirstOff;
  222. PAnsiRec(NewDestP-AnsiFirstOff)^.ElementSize:=1;
  223. PAnsiRec(NewDestP-AnsiFirstOff)^.Ref:=1;
  224. Move(Pointer(S1)^,NewDestP^,S1Len);
  225. Move(Pointer(S2)^,PAnsiChar(NewDestP)[S1Len],S2Len);
  226. fpc_ansistr_decr_ref(Pointer(DestS));
  227. end;
  228. PAnsiChar(NewDestP)[S1Len+S2Len]:=#0;
  229. PAnsiRec(NewDestP-AnsiFirstOff)^.CodePage:=DestCP;
  230. PAnsiRec(NewDestP-AnsiFirstOff)^.Len:=S1Len+S2Len;
  231. Pointer(DestS):=NewDestP;
  232. end;
  233. {$endif FPC_HAS_ANSISTR_CONCAT}
  234. {$ifndef FPC_HAS_ANSISTR_CONCAT_MULTI}
  235. {$define FPC_HAS_ANSISTR_CONCAT_MULTI}
  236. procedure AnsiStr_Concat_multi_complex(var DestS:RawByteString;const sarr:array of RawByteString;cp:TSystemCodePage);
  237. var
  238. i : ObjpasInt;
  239. U : UnicodeString;
  240. begin
  241. U:='';
  242. for i:=0 to high(sarr) do
  243. if (Length(sarr[i])<>0) then
  244. U:=U+UnicodeString(sarr[i]);
  245. DestS:='';
  246. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(U)),DestS,cp,Length(U));
  247. end;
  248. procedure fpc_AnsiStr_Concat_multi (var DestS:RawByteString;const sarr:array of RawByteString;cp : TSystemCodePage); compilerproc;
  249. Var
  250. lowstart,i,Size,NewLen : SizeInt;
  251. p,pc,olddestp,newdestp,realdestp : pointer;
  252. DestCP,tmpCP : TSystemCodePage;
  253. begin
  254. DestCP:=cp;
  255. if DestCp=CP_NONE then
  256. DestCP:=DefaultSystemCodePage;
  257. lowstart:=low(sarr);
  258. { skip empty strings }
  259. while (lowstart<=high(sarr)) and
  260. (Length(sarr[lowstart])=0) do
  261. inc(lowstart);
  262. if lowstart>high(sarr) then
  263. begin
  264. DestS:=''; { All source strings empty }
  265. exit;
  266. end;
  267. DestCP:=TranslatePlaceholderCP(DestCP);
  268. tmpCP:=TranslatePlaceholderCP(StringCodePage(sarr[lowstart]));
  269. for i:=lowstart+1 to high(sarr) do
  270. begin
  271. { ignore the code page of empty strings, it will always be
  272. DefaultSystemCodePage but it doesn't matter for the outcome }
  273. if (length(sarr[i])<>0) and
  274. (tmpCP<>TranslatePlaceholderCP(StringCodePage(sarr[i]))) then
  275. begin
  276. AnsiStr_Concat_multi_complex(DestS,sarr,DestCP);
  277. exit;
  278. end;
  279. end;
  280. { if the result is rawbytestring and all strings have the same code page,
  281. keep that code page }
  282. if cp=CP_NONE then
  283. DestCP:=tmpCP;
  284. { Calculate size of the result so we can do
  285. a single call to SetLength() }
  286. NewLen:=0;
  287. for i:=lowstart to high(sarr) do
  288. inc(NewLen,length(sarr[i]));
  289. { In the case of the only nonempty string, either return it directly (if SetCodePage has nothing to do) or skip 1 allocation. }
  290. if NewLen=PAnsiRec(Pointer(sarr[lowstart])-AnsiFirstOff)^.Len then
  291. DestS:=sarr[lowstart]
  292. else
  293. begin
  294. olddestp:=pointer(dests);
  295. { Reallocate when possible; in the hope this will reuse the chunk more often than do a redundant copy. }
  296. if assigned(olddestp) and (PAnsiRec(olddestp-AnsiFirstOff)^.Ref=1) then
  297. begin
  298. realdestp:=olddestp-AnsiFirstOff;
  299. newdestp:=ReallocMem(realdestp,AnsiFirstOff+1+NewLen)+AnsiFirstOff;
  300. { First string can be skipped if appending. }
  301. if olddestp=pointer(sarr[lowstart]) then
  302. inc(lowstart);
  303. end
  304. else
  305. begin
  306. { Create new string. }
  307. olddestp:=nil; { This case is distinguished as "not assigned(olddestp)". Also prevents "if p=olddestp" in the loop below shared with the ReallocMem branch. }
  308. newdestp:=GetMem(NewLen+(AnsiFirstOff+1))+AnsiFirstOff;
  309. PAnsiRec(newdestp-AnsiFirstOff)^.ElementSize:=1;
  310. PAnsiRec(newdestp-AnsiFirstOff)^.Ref:=1;
  311. end;
  312. { Copy strings from last to the first, so that possible occurences of DestS could read from the beginning of the reallocated DestS. }
  313. pc:=newdestp+NewLen;
  314. PByte(pc)^:=0; { Conveniently write null terminator. }
  315. for i:=high(sarr) downto lowstart do
  316. begin
  317. p:=pointer(sarr[i]);
  318. if not assigned(p) then
  319. continue;
  320. if p=olddestp then
  321. { DestS occured among pieces in the ReallocMem case! Use the new pointer. Its header still conveniently contains old DestS length. }
  322. p:=newdestp;
  323. Size:=PAnsiRec(p-AnsiFirstOff)^.Len;
  324. dec(pc,size);
  325. Move(p^,pc^,Size);
  326. end;
  327. PAnsiRec(newdestp-AnsiFirstOff)^.CodePage:=tmpCP;
  328. PAnsiRec(newdestp-AnsiFirstOff)^.Len:=NewLen; { Careful, loop above relies on the old Len in the newdestp header. }
  329. if not assigned(olddestp) then
  330. fpc_AnsiStr_Decr_Ref(pointer(DestS));
  331. Pointer(DestS):=newdestp;
  332. end;
  333. { SetCodePage does the conversion (or at least uniquifying) if DestCP is not exactly the code page stored in the string header. Avoid if possible. }
  334. if DestCP<>tmpCP then
  335. SetCodePage(DestS,DestCP,True);
  336. end;
  337. {$endif FPC_HAS_ANSISTR_CONCAT_MULTI}
  338. {$ifdef EXTRAANSISHORT}
  339. Procedure fpc_AnsiStr_ShortStr_Concat (Var S1: AnsiString; Var S2 : ShortString);
  340. {
  341. Concatenates a Ansi with a short string; : S2 + S2
  342. }
  343. Var
  344. Size,Location : SizeInt;
  345. begin
  346. Size:=Length(S2);
  347. Location:=Length(S1);
  348. If Size=0 then
  349. exit;
  350. { Setlength takes case of uniqueness
  351. and alllocated memory. We need to use length,
  352. to take into account possibility of S1=Nil }
  353. SetLength (S1,Size+Length(S1));
  354. Move (S2[1],Pointer(Pointer(S1)+Location)^,Size);
  355. PByte( Pointer(S1)+length(S1) )^:=0; { Terminating Zero }
  356. end;
  357. {$endif EXTRAANSISHORT}
  358. {$ifndef FPC_HAS_ANSISTR_TO_ANSISTR}
  359. {$define FPC_HAS_ANSISTR_TO_ANSISTR}
  360. Function fpc_AnsiStr_To_AnsiStr (const S : RawByteString;cp : TSystemCodePage): RawByteString; [Public, alias: 'FPC_ANSISTR_TO_ANSISTR']; compilerproc;
  361. {
  362. Converts an AnsiString to an AnsiString taking code pages into care
  363. }
  364. Var
  365. Size : SizeInt;
  366. temp : UnicodeString;
  367. orgcp: TSystemCodePage;
  368. begin
  369. result:='';
  370. Size:=Length(S);
  371. if Size>0 then
  372. begin
  373. cp:=TranslatePlaceholderCP(cp);
  374. orgcp:=TranslatePlaceholderCP(StringCodePage(S));
  375. if (orgcp=cp) or (orgcp=CP_NONE) then
  376. begin
  377. SetLength(result,Size);
  378. Move(S[1],result[1],Size);
  379. PAnsiRec(Pointer(result)-AnsiFirstOff)^.CodePage:=cp;
  380. end
  381. else
  382. begin
  383. temp:=UnicodeString(S);
  384. Size:=Length(temp);
  385. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(temp)),result,cp,Size);
  386. end;
  387. end;
  388. end;
  389. Function fpc_AnsiStr_To_AnsiStr (const S : RawByteString;cp : TSystemCodePage): RawByteString; [external name 'FPC_ANSISTR_TO_ANSISTR'];
  390. {$endif FPC_HAS_ANSISTR_TO_ANSISTR}
  391. {$ifndef FPC_HAS_ANSISTR_TO_SHORTSTR}
  392. {$define FPC_HAS_ANSISTR_TO_SHORTSTR}
  393. procedure fpc_AnsiStr_To_ShortStr (out res: shortstring; const S2 : RawByteString);[Public, alias: 'FPC_ANSISTR_TO_SHORTSTR']; compilerproc;
  394. {
  395. Converts a AnsiString to a ShortString;
  396. }
  397. Var
  398. Size : SizeInt;
  399. begin
  400. if Length(S2)=0 then
  401. res:=''
  402. else
  403. begin
  404. Size:=Length(S2);
  405. If Size>high(res) then
  406. Size:=high(res);
  407. byte(res[0]):=byte(Size);
  408. Move (S2[1],res[1],Size);
  409. end;
  410. end;
  411. {$endif FPC_HAS_ANSISTR_TO_SHORTSTR}
  412. {$ifndef FPC_HAS_SHORTSTR_TO_ANSISTR}
  413. {$define FPC_HAS_SHORTSTR_TO_ANSISTR}
  414. Function fpc_ShortStr_To_AnsiStr (Const S2 : ShortString;cp : TSystemCodePage): RawByteString; compilerproc;
  415. {
  416. Converts a ShortString to a AnsiString;
  417. }
  418. Var
  419. Size : SizeInt;
  420. begin
  421. Size:=Length(S2);
  422. Setlength(fpc_ShortStr_To_AnsiStr,Size);
  423. if Size>0 then
  424. begin
  425. fpc_shortstr_ansistr_intern_charmove(S2,1,fpc_ShortStr_To_AnsiStr,0,Size);
  426. SetCodePage(fpc_ShortStr_To_AnsiStr,TranslatePlaceholderCP(cp),False);
  427. end
  428. end;
  429. {$endif FPC_HAS_SHORTSTR_TO_ANSISTR}
  430. {$ifndef FPC_HAS_CHAR_TO_ANSISTR}
  431. {$define FPC_HAS_CHAR_TO_ANSISTR}
  432. Function fpc_Char_To_AnsiStr(const c : AnsiChar;cp : TSystemCodePage): RawByteString; compilerproc;
  433. {
  434. Converts a AnsiChar to a AnsiString;
  435. }
  436. begin
  437. Setlength (fpc_Char_To_AnsiStr,1);
  438. PAnsiChar(fpc_Char_To_AnsiStr)^:=c;
  439. { Terminating Zero already set by SetLength above }
  440. SetCodePage(fpc_Char_To_AnsiStr,TranslatePlaceholderCP(cp),False);
  441. end;
  442. {$endif FPC_HAS_CHAR_TO_ANSISTR}
  443. {$ifndef FPC_HAS_PCHAR_TO_ANSISTR}
  444. {$define FPC_HAS_PCHAR_TO_ANSISTR}
  445. Function fpc_PChar_To_AnsiStr(const p : PAnsiChar;cp : TSystemCodePage): RawByteString; compilerproc;
  446. Var
  447. L : SizeInt;
  448. begin
  449. if (not assigned(p)) or (p[0]=#0) Then
  450. L := 0
  451. else
  452. L:=IndexChar(p^,-1,#0);
  453. SetLength(fpc_PChar_To_AnsiStr,L);
  454. if L > 0 then
  455. begin
  456. fpc_pchar_ansistr_intern_charmove(p,0,fpc_PChar_To_AnsiStr,0,L);
  457. SetCodePage(fpc_PChar_To_AnsiStr,TranslatePlaceholderCP(cp),False);
  458. end;
  459. end;
  460. {$endif FPC_HAS_PCHAR_TO_ANSISTR}
  461. {$ifndef FPC_HAS_CHARARRAY_TO_ANSISTR}
  462. {$define FPC_HAS_CHARARRAY_TO_ANSISTR}
  463. Function fpc_CharArray_To_AnsiStr(const arr: array of ansichar; cp : TSystemCodePage;zerobased: boolean = true): RawByteString; compilerproc;
  464. var
  465. i : SizeInt;
  466. begin
  467. if (zerobased) then
  468. begin
  469. if (arr[0]=#0) Then
  470. i := 0
  471. else
  472. begin
  473. i:=IndexChar(arr,high(arr)+1,#0);
  474. if i = -1 then
  475. i := high(arr)+1;
  476. end;
  477. end
  478. else
  479. i := high(arr)+1;
  480. SetLength(fpc_CharArray_To_AnsiStr,i);
  481. if i > 0 then
  482. begin
  483. fpc_pchar_ansistr_intern_charmove(pansichar(@arr),0,fpc_CharArray_To_AnsiStr,0,i);
  484. SetCodePage(fpc_CharArray_To_AnsiStr,TranslatePlaceholderCP(cp),False);
  485. end;
  486. end;
  487. {$endif FPC_HAS_ANSISTR_TO_CHARARRAY}
  488. {$ifndef FPC_HAS_ANSISTR_TO_CHARARRAY}
  489. {$define FPC_HAS_ANSISTR_TO_CHARARRAY}
  490. procedure fpc_ansistr_to_chararray(out res: array of AnsiChar; const src: RawByteString); compilerproc;
  491. var
  492. len: SizeInt;
  493. begin
  494. len := length(src);
  495. if len > length(res) then
  496. len := length(res);
  497. {$push}{$r-}
  498. { make sure we don't try to access element 1 of the ansistring if it's nil }
  499. if len > 0 then
  500. move(src[1],res[0],len);
  501. fillchar(res[len],length(res)-len,0);
  502. {$pop}
  503. end;
  504. {$endif FPC_HAS_ANSISTR_TO_CHARARRAY}
  505. {$ifndef FPC_HAS_ANSISTR_COMPARE}
  506. {$define FPC_HAS_ANSISTR_COMPARE}
  507. Function fpc_utf8_Compare(const S1,S2 : RawByteString): SizeInt;
  508. var
  509. r1,r2 : RawByteString;
  510. begin
  511. r1:=S1;
  512. r2:=S2;
  513. //convert them to utf8 then compare
  514. SetCodePage(r1,65001);
  515. SetCodePage(r2,65001);
  516. Result:=fpc_AnsiStr_Compare(r1,r2);
  517. end;
  518. Function fpc_AnsiStr_Compare(const S1,S2 : RawByteString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE']; compilerproc;
  519. {
  520. Compares 2 AnsiStrings;
  521. The result is
  522. <0 if S1<S2
  523. 0 if S1=S2
  524. >0 if S1>S2
  525. }
  526. Var
  527. Len1,Len2,CmpLen : SizeInt;
  528. begin
  529. if (pointer(S1)=pointer(S2)) or (pointer(S1)=nil) or (pointer(S2)=nil) then
  530. exit(ord(pointer(S1)<>nil)-ord(pointer(S2)<>nil));
  531. if TranslatePlaceholderCP(PAnsiRec(Pointer(S1)-AnsiFirstOff)^.CodePage)<>TranslatePlaceholderCP(PAnsiRec(Pointer(S2)-AnsiFirstOff)^.CodePage) then
  532. exit(fpc_utf8_compare(s1,s2));
  533. Len1:=PAnsiRec(Pointer(S1)-AnsiFirstOff)^.Len;
  534. Len2:=PAnsiRec(Pointer(S2)-AnsiFirstOff)^.Len;
  535. CmpLen:=Len1;
  536. If Len1>Len2 then
  537. CmpLen:=Len2;
  538. result:=CompareByte(S1[1],S2[1],CmpLen);
  539. if result=0 then
  540. result:=Len1-Len2;
  541. end;
  542. {$endif FPC_HAS_ANSISTR_COMPARE}
  543. {$ifndef FPC_HAS_ANSISTR_COMPARE_EQUAL}
  544. {$define FPC_HAS_ANSISTR_COMPARE_EQUAL}
  545. Function fpc_utf8_Compare_equal(Const S1,S2 : RawByteString): SizeInt;
  546. Var
  547. r1,r2 : RawByteString;
  548. L1,L2 : SizeInt;
  549. begin
  550. r1:=S1;
  551. r2:=S2;
  552. //convert them to utf8 then compare
  553. SetCodePage(r1,65001);
  554. SetCodePage(r2,65001);
  555. L1:=Length(r1);
  556. L2:=Length(r2);
  557. Result:=L1-L2;
  558. if Result = 0 then
  559. if L1>0 then
  560. result:=CompareByte(r1[1],r2[1],L1);
  561. end;
  562. Function fpc_AnsiStr_Compare_equal(const S1,S2 : RawByteString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE_EQUAL']; compilerproc;
  563. {
  564. Compares 2 AnsiStrings for equality/inequality only;
  565. The result is
  566. 0 if S1=S2
  567. <>0 if S1<>S2
  568. }
  569. Var
  570. MaxI : SizeInt;
  571. begin
  572. { don't compare strings if one of them is empty }
  573. if (pointer(S1)=pointer(S2)) or (pointer(S1)=nil) or (pointer(S2)=nil) then
  574. Exit(ord(pointer(S1)<>pointer(S2)));
  575. if TranslatePlaceholderCP(PAnsiRec(Pointer(S1)-AnsiFirstOff)^.CodePage)<>TranslatePlaceholderCP(PAnsiRec(Pointer(S2)-AnsiFirstOff)^.CodePage) then
  576. Exit(fpc_utf8_Compare_equal(S1,S2));
  577. Maxi:=PAnsiRec(Pointer(S1)-AnsiFirstOff)^.Len;
  578. Result:=Maxi-PAnsiRec(Pointer(S2)-AnsiFirstOff)^.Len;
  579. if Result=0 then
  580. result:=CompareByte(S1[1],S2[1],MaxI);
  581. end;
  582. {$endif FPC_HAS_ANSISTR_COMPARE_EQUAL}
  583. {$ifndef FPC_HAS_ANSISTR_RANGECHECK}
  584. {$define FPC_HAS_ANSISTR_RANGECHECK}
  585. Procedure fpc_AnsiStr_RangeCheck(p: Pointer; index: SizeInt);[Public,Alias : 'FPC_ANSISTR_RANGECHECK']; compilerproc;
  586. begin
  587. if (p=nil) or (index>PAnsiRec(p-AnsiFirstOff)^.Len) or (Index<1) then
  588. HandleErrorAddrFrameInd(201,get_pc_addr,get_frame);
  589. end;
  590. Procedure fpc_AnsiStr_ZeroBased_RangeCheck(p: Pointer; index: SizeInt);[Public,Alias : 'FPC_ANSISTR_ZEROBASED_RANGECHECK']; compilerproc;
  591. begin
  592. if (p=nil) or (index>=PAnsiRec(p-AnsiFirstOff)^.Len) or (Index<0) then
  593. HandleErrorAddrFrameInd(201,get_pc_addr,get_frame);
  594. end;
  595. {$endif FPC_HAS_ANSISTR_RANGECHECK}
  596. {$ifndef FPC_HAS_ANSISTR_SETLENGTH}
  597. {$define FPC_HAS_ANSISTR_SETLENGTH}
  598. Procedure fpc_AnsiStr_SetLength (Var S : RawByteString; l : SizeInt;cp : TSystemCodePage);[Public,Alias : 'FPC_ANSISTR_SETLENGTH']; compilerproc;
  599. {
  600. Sets The length of string S to L.
  601. Makes sure S is unique, and contains enough room.
  602. }
  603. Var
  604. sp,oldsp,realsp : Pointer;
  605. lens, lena : SizeInt;
  606. begin
  607. if l<=0 then { length=0, deallocate the string }
  608. begin
  609. fpc_ansistr_decr_ref (Pointer(S));
  610. exit;
  611. end;
  612. sp:=Pointer(S);
  613. if (sp<>nil) and (PAnsiRec(sp-AnsiFirstOff)^.Ref=1) then
  614. begin
  615. lens:=MemSize(sp-AnsiFirstOff);
  616. lena:=L+(AnsiFirstOff+1);
  617. { allow shrinking string if that saves at least half of current size }
  618. if (lena>lens) or (lena+32<=SizeInt(SizeUint(lens) div 2)) then
  619. begin
  620. realsp:=sp-AnsiFirstOff; { Avoid taking sp address. }
  621. sp:=reallocmem(realsp,lena)+AnsiFirstOff;
  622. end;
  623. end
  624. else
  625. begin
  626. { Reallocation is needed... }
  627. oldsp:=sp;
  628. sp:=GetMem(L+(AnsiFirstOff+1))+AnsiFirstOff;
  629. PAnsiRec(sp-AnsiFirstOff)^.ElementSize:=1;
  630. PAnsiRec(sp-AnsiFirstOff)^.Ref:=1;
  631. if oldsp=nil then
  632. PAnsiRec(sp-AnsiFirstOff)^.CodePage:=TranslatePlaceholderCP(cp)
  633. else
  634. begin
  635. PAnsiRec(sp-AnsiFirstOff)^.CodePage:=PAnsiRec(oldsp-AnsiFirstOff)^.CodePage;
  636. lens:=PAnsiRec(oldsp-AnsiFirstOff)^.Len;
  637. if l<lens then
  638. lens:=l;
  639. Move(oldsp^,sp^,lens);
  640. fpc_ansistr_decr_ref(Pointer(s));
  641. end;
  642. end;
  643. { Null-terminate. }
  644. PByte(sp+l)^:=0;
  645. PAnsiRec(sp-AnsiFirstOff)^.Len:=l;
  646. Pointer(S):=sp;
  647. end;
  648. {$endif FPC_HAS_ANSISTR_SETLENGTH}
  649. {$ifdef EXTRAANSISHORT}
  650. Function fpc_AnsiStr_ShortStr_Compare (Var S1 : Pointer; Var S2 : ShortString): SizeInt; compilerproc;
  651. {
  652. Compares a AnsiString with a ShortString;
  653. The result is
  654. <0 if S1<S2
  655. 0 if S1=S2
  656. >0 if S1>S2
  657. }
  658. Var
  659. i,MaxI,Temp : SizeInt;
  660. begin
  661. Temp:=0;
  662. i:=0;
  663. MaxI:=Length(AnsiString(S1));
  664. if MaxI>byte(S2[0]) then
  665. MaxI:=Byte(S2[0]);
  666. While (i<MaxI) and (Temp=0) do
  667. begin
  668. Temp:= PByte(S1+I)^ - Byte(S2[i+1]);
  669. inc(i);
  670. end;
  671. AnsiStr_ShortStr_Compare:=Temp;
  672. end;
  673. {$endif EXTRAANSISHORT}
  674. {*****************************************************************************
  675. Public functions, In interface.
  676. *****************************************************************************}
  677. {$ifndef FPC_SYSTEM_HAS_TRUELY_ANSISTR_UNIQUE}
  678. {$define FPC_SYSTEM_HAS_TRUELY_ANSISTR_UNIQUE}
  679. function fpc_truely_ansistr_unique(Var S : Pointer): Pointer;
  680. Var
  681. Sp : Pointer;
  682. FullSize : SizeInt;
  683. begin
  684. Sp:=S;
  685. FullSize:=PAnsiRec(Sp-AnsiFirstOff)^.len+(AnsiFirstOff+1);
  686. result:=GetMem(FullSize)+AnsiFirstOff;
  687. Move ((Sp-AnsiFirstOff)^,(result-AnsiFirstOff)^,FullSize); { Copy everything including header and #0, only refcount needs to be adjusted. }
  688. PAnsiRec(result-AnsiFirstOff)^.Ref:=1;
  689. fpc_ansistr_decr_ref (S); { Thread safe }
  690. S:=result;
  691. end;
  692. {$endif FPC_SYSTEM_HAS_TRUELY_ANSISTR_UNIQUE}
  693. Function fpc_ansistr_Unique_func(Var S : RawByteString): Pointer; external name 'FPC_ANSISTR_UNIQUE';
  694. Procedure UniqueString(var S : RawByteString);rtlproc;{$ifdef SYSTEMINLINE}inline;{$endif}
  695. begin
  696. fpc_ansistr_Unique_func(S);
  697. end;
  698. {$ifndef FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  699. {$define FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  700. // MV: inline the basic checks for case that S is already unique.
  701. // Rest is too complex to inline, so factor that out as a call.
  702. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; compilerproc; inline;
  703. {
  704. Make sure reference count of S is 1,
  705. using copy-on-write semantics.
  706. }
  707. begin
  708. pointer(result) := pointer(s);
  709. if (result<>Nil) and (PAnsiRec(result-AnsiFirstOff)^.Ref<>1) then
  710. result:=fpc_truely_ansistr_unique(s);
  711. end;
  712. {$endif FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  713. {$ifndef FPC_HAS_ANSISTR_COPY}
  714. {$define FPC_HAS_ANSISTR_COPY}
  715. Function Fpc_Ansistr_Copy(Const S : RawByteString; Index,Size : SizeInt): RawByteString;compilerproc;
  716. var
  717. Lim : SizeInt;
  718. ResultAddress : Pointer;
  719. begin
  720. ResultAddress:=Nil;
  721. if Index < 1 then
  722. Index := 1;
  723. dec(index);
  724. Lim:=Length(S)-Index; { Cannot overflow as both Length(S) and Index are non-negative. }
  725. if Size>Lim then
  726. Size:=Lim;
  727. If Size>0 then
  728. begin
  729. ResultAddress:=GetMem(Size+(AnsiFirstOff+1))+AnsiFirstOff;
  730. PAnsiRec(ResultAddress-AnsiFirstOff)^.CodePage:=PAnsiRec(Pointer(S)-AnsiFirstOff)^.CodePage;
  731. PAnsiRec(ResultAddress-AnsiFirstOff)^.ElementSize:=1;
  732. PAnsiRec(ResultAddress-AnsiFirstOff)^.Ref:=1;
  733. PAnsiRec(ResultAddress-AnsiFirstOff)^.Len:=Size;
  734. Move(Pointer(Pointer(S)+index)^,ResultAddress^,Size);
  735. PByte(ResultAddress)[Size]:=0;
  736. end;
  737. fpc_ansistr_decr_ref(Pointer(fpc_ansistr_copy));
  738. Pointer(fpc_ansistr_Copy):=ResultAddress;
  739. end;
  740. {$endif FPC_HAS_ANSISTR_COPY}
  741. {$ifndef FPC_HAS_POS_SHORTSTR_ANSISTR}
  742. {$define FPC_HAS_POS_SHORTSTR_ANSISTR}
  743. Function Pos(Const Substr : ShortString; Const Source : RawByteString; Offset : Sizeint = 1) : SizeInt;
  744. var
  745. nsource : SizeInt;
  746. begin
  747. nsource:=Length(Source);
  748. result:=0;
  749. dec(Offset);
  750. if SizeUint(Offset)<SizeUint(nsource) then { (Offset >= 0) and (Offset < nsource) }
  751. result:=MemPos(PByte(@Substr[1]),length(Substr),PByte(Source)+Offset,nsource-Offset)+1;
  752. if result>0 then
  753. inc(result,Offset);
  754. end;
  755. {$endif FPC_HAS_POS_SHORTSTR_ANSISTR}
  756. {$ifndef FPC_HAS_POS_ANSISTR_ANSISTR}
  757. {$define FPC_HAS_POS_ANSISTR_ANSISTR}
  758. Function Pos(Const Substr : RawByteString; Const Source : RawByteString; Offset : Sizeint = 1) : SizeInt;
  759. var
  760. nsource : SizeInt;
  761. begin
  762. nsource:=Length(Source);
  763. result:=0;
  764. dec(Offset);
  765. if SizeUint(Offset)<SizeUint(nsource) then { (Offset >= 0) and (Offset < nsource) }
  766. result:=MemPos(PByte(Substr),length(Substr),PByte(Source)+Offset,nsource-Offset)+1;
  767. if result>0 then
  768. inc(result,Offset);
  769. end;
  770. {$endif FPC_HAS_POS_ANSISTR_ANSISTR}
  771. {$ifndef FPC_HAS_POS_ANSICHAR_ANSISTR}
  772. {$define FPC_HAS_POS_ANSICHAR_ANSISTR}
  773. { Faster version for a AnsiChar alone. Must be implemented because }
  774. { pos(c: AnsiChar; const s: shortstring) also exists, so otherwise }
  775. { using pos(AnsiChar,pansichar) will always call the shortstring version }
  776. { (exact match for first argument), also with $h+ (JM) }
  777. Function Pos(c : AnsiChar; Const s : RawByteString; Offset : Sizeint = 1) : SizeInt;
  778. var
  779. ns,idx: SizeInt;
  780. begin
  781. pos:=0;
  782. ns:=length(s);
  783. if (Offset>0) and (Offset<=ns) then
  784. begin
  785. idx:=IndexByte(s[Offset],ns-Offset+1,byte(c));
  786. if idx>=0 then
  787. pos:=Offset+idx;
  788. end;
  789. end;
  790. {$endif FPC_HAS_POS_ANSICHAR_ANSISTR}
  791. {$ifndef FPUNONE}
  792. Function fpc_Val_Real_AnsiStr(Const S : RawByteString; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_ANSISTR']; compilerproc;
  793. Var
  794. SS : ShortString;
  795. begin
  796. fpc_Val_Real_AnsiStr := 0;
  797. if length(S) > 255 then
  798. code := 256
  799. else
  800. begin
  801. SS := S;
  802. Val(SS,fpc_Val_Real_AnsiStr,code);
  803. end;
  804. end;
  805. {$endif}
  806. Function fpc_Val_Currency_AnsiStr(Const S : RawByteString; out Code : ValSInt): Currency; [public, alias:'FPC_VAL_CURRENCY_ANSISTR']; compilerproc;
  807. Var
  808. SS : ShortString;
  809. begin
  810. if length(S) > 255 then
  811. begin
  812. fpc_Val_Currency_AnsiStr := 0;
  813. code := 256;
  814. end
  815. else
  816. begin
  817. SS := S;
  818. Val(SS,fpc_Val_Currency_AnsiStr,code);
  819. end;
  820. end;
  821. Function fpc_Val_UInt_AnsiStr ({$ifndef VER3_2}DestSize: SizeInt;{$endif VER3_2} Const S : RawByteString; out Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_ANSISTR']; compilerproc;
  822. Var
  823. SS : ShortString;
  824. begin
  825. fpc_Val_UInt_AnsiStr := 0;
  826. if length(S) > 255 then
  827. code := 256
  828. else
  829. begin
  830. SS := S;
  831. Val(SS,fpc_Val_UInt_AnsiStr,code);
  832. end;
  833. end;
  834. Function fpc_Val_SInt_AnsiStr (DestSize: SizeInt; Const S : RawByteString; out Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_ANSISTR']; compilerproc;
  835. Var
  836. SS : ShortString;
  837. begin
  838. fpc_Val_SInt_AnsiStr:=0;
  839. if length(S)>255 then
  840. code:=256
  841. else
  842. begin
  843. SS := S;
  844. fpc_Val_SInt_AnsiStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  845. end;
  846. end;
  847. {$ifndef CPU64}
  848. Function fpc_Val_qword_AnsiStr (Const S : RawByteString; out Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_ANSISTR']; compilerproc;
  849. Var
  850. SS : ShortString;
  851. begin
  852. fpc_Val_qword_AnsiStr:=0;
  853. if length(S)>255 then
  854. code:=256
  855. else
  856. begin
  857. SS := S;
  858. Val(SS,fpc_Val_qword_AnsiStr,Code);
  859. end;
  860. end;
  861. Function fpc_Val_int64_AnsiStr (Const S : RawByteString; out Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_ANSISTR']; compilerproc;
  862. Var
  863. SS : ShortString;
  864. begin
  865. fpc_Val_int64_AnsiStr:=0;
  866. if length(S)>255 then
  867. code:=256
  868. else
  869. begin
  870. SS := s;
  871. Val(SS,fpc_Val_int64_AnsiStr,Code);
  872. end;
  873. end;
  874. {$endif CPU64}
  875. {$if defined(CPU16) or defined(CPU8)}
  876. Function fpc_Val_longword_AnsiStr (Const S : RawByteString; out Code : ValSInt): longword; [public, alias:'FPC_VAL_LONGWORD_ANSISTR']; compilerproc;
  877. Var
  878. SS : ShortString;
  879. begin
  880. fpc_Val_longword_AnsiStr:=0;
  881. if length(S)>255 then
  882. code:=256
  883. else
  884. begin
  885. SS := S;
  886. Val(SS,fpc_Val_longword_AnsiStr,Code);
  887. end;
  888. end;
  889. Function fpc_Val_longint_AnsiStr (Const S : RawByteString; out Code : ValSInt): LongInt; [public, alias:'FPC_VAL_LONGINT_ANSISTR']; compilerproc;
  890. Var
  891. SS : ShortString;
  892. begin
  893. fpc_Val_longint_AnsiStr:=0;
  894. if length(S)>255 then
  895. code:=256
  896. else
  897. begin
  898. SS := s;
  899. Val(SS,fpc_Val_longint_AnsiStr,Code);
  900. end;
  901. end;
  902. Function fpc_Val_word_AnsiStr (Const S : RawByteString; out Code : ValSInt): word; [public, alias:'FPC_VAL_WORD_ANSISTR']; compilerproc;
  903. Var
  904. SS : ShortString;
  905. begin
  906. fpc_Val_word_AnsiStr:=0;
  907. if length(S)>255 then
  908. code:=256
  909. else
  910. begin
  911. SS := S;
  912. Val(SS,fpc_Val_word_AnsiStr,Code);
  913. end;
  914. end;
  915. Function fpc_Val_smallint_AnsiStr (Const S : RawByteString; out Code : ValSInt): smallint; [public, alias:'FPC_VAL_SMALLINT_ANSISTR']; compilerproc;
  916. Var
  917. SS : ShortString;
  918. begin
  919. fpc_Val_smallint_AnsiStr:=0;
  920. if length(S)>255 then
  921. code:=256
  922. else
  923. begin
  924. SS := s;
  925. Val(SS,fpc_Val_smallint_AnsiStr,Code);
  926. end;
  927. end;
  928. {$endif CPU16 or CPU8}
  929. {$if defined(CPU8)}
  930. Function fpc_Val_word_AnsiStr (Const S : RawByteString; out Code : ValSInt): longword; [public, alias:'FPC_VAL_WORD_ANSISTR']; compilerproc;
  931. Var
  932. SS : ShortString;
  933. begin
  934. fpc_Val_longword_AnsiStr:=0;
  935. if length(S)>255 then
  936. code:=256
  937. else
  938. begin
  939. SS := S;
  940. Val(SS,fpc_Val_longword_AnsiStr,Code);
  941. end;
  942. end;
  943. Function fpc_Val_smallint_AnsiStr (Const S : RawByteString; out Code : ValSInt): LongInt; [public, alias:'FPC_VAL_SMALLINT_ANSISTR']; compilerproc;
  944. Var
  945. SS : ShortString;
  946. begin
  947. fpc_Val_longint_AnsiStr:=0;
  948. if length(S)>255 then
  949. code:=256
  950. else
  951. begin
  952. SS := s;
  953. Val(SS,fpc_Val_longint_AnsiStr,Code);
  954. end;
  955. end;
  956. {$endif CPU8}
  957. {$ifndef FPUNONE}
  958. procedure fpc_AnsiStr_Float(d : ValReal;len,fr,rt : SizeInt;out s : RawByteString;cp : TSystemCodePage);[public,alias:'FPC_ANSISTR_FLOAT']; compilerproc; inline;
  959. var
  960. ss: ShortString;
  961. begin
  962. str_real(len,fr,d,treal_type(rt),ss);
  963. s:=ss;
  964. SetCodePage(s,cp,false);
  965. end;
  966. {$endif}
  967. {$ifndef FPC_STR_ENUM_INTERN}
  968. procedure fpc_ansistr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:RawByteString;cp : TSystemCodePage);[public,alias:'FPC_ANSISTR_ENUM'];compilerproc; inline;
  969. var ss:shortstring;
  970. begin
  971. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  972. s:=ss;
  973. SetCodePage(s,cp,false);
  974. end;
  975. {$endif FPC_STR_ENUM_INTERN}
  976. procedure fpc_ansistr_bool(b : boolean;len:sizeint;out s:RawByteString;cp : TSystemCodePage);[public,alias:'FPC_ANSISTR_BOOL'];compilerproc; inline;
  977. var
  978. ss:shortstring;
  979. begin
  980. fpc_shortstr_bool(b,len,ss);
  981. s:=ss;
  982. SetCodePage(s,cp,false);
  983. end;
  984. {$ifndef FPC_STR_ENUM_INTERN}
  985. function fpc_val_enum_ansistr(str2ordindex:pointer;const s:RawByteString;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_ANSISTR']; compilerproc;
  986. begin
  987. fpc_val_enum_ansistr:=fpc_val_enum_shortstr(str2ordindex,s,code);
  988. end;
  989. {$endif FPC_STR_ENUM_INTERN}
  990. procedure fpc_AnsiStr_Currency(c : currency;len,fr : SizeInt;out s : RawByteString;cp : TSystemCodePage);[public,alias:'FPC_ANSISTR_CURRENCY']; compilerproc; inline;
  991. var
  992. ss: ShortString;
  993. begin
  994. str(c:len:fr,ss);
  995. s:=ss;
  996. SetCodePage(s,cp,false);
  997. end;
  998. Procedure fpc_AnsiStr_UInt(v : ValUInt;Len : SizeInt; out S : RawByteString;cp : TSystemCodePage);[Public,Alias : 'FPC_ANSISTR_VALUINT']; compilerproc; inline;
  999. Var
  1000. SS : ShortString;
  1001. begin
  1002. str(v:Len,SS);
  1003. S:=SS;
  1004. SetCodePage(s,cp,false);
  1005. end;
  1006. Procedure fpc_AnsiStr_SInt(v : ValSInt;Len : SizeInt; out S : RawByteString;cp : TSystemCodePage);[Public,Alias : 'FPC_ANSISTR_VALSINT']; compilerproc; inline;
  1007. Var
  1008. SS : ShortString;
  1009. begin
  1010. str (v:Len,SS);
  1011. S:=SS;
  1012. SetCodePage(s,cp,false);
  1013. end;
  1014. {$ifndef CPU64}
  1015. Procedure fpc_AnsiStr_QWord(v : QWord;Len : SizeInt; out S : RawByteString;cp : TSystemCodePage);[Public,Alias : 'FPC_ANSISTR_QWORD']; compilerproc; inline;
  1016. Var
  1017. SS : ShortString;
  1018. begin
  1019. str(v:Len,SS);
  1020. S:=SS;
  1021. SetCodePage(s,cp,false);
  1022. end;
  1023. Procedure fpc_AnsiStr_Int64(v : Int64; Len : SizeInt; out S : RawByteString;cp : TSystemCodePage);[Public,Alias : 'FPC_ANSISTR_INT64']; compilerproc; inline;
  1024. Var
  1025. SS : ShortString;
  1026. begin
  1027. str (v:Len,SS);
  1028. S:=SS;
  1029. SetCodePage(s,cp,false);
  1030. end;
  1031. {$endif CPU64}
  1032. {$if defined(CPU16) or defined(CPU8)}
  1033. Procedure fpc_AnsiStr_LongWord(v : LongWord;Len : SizeInt; out S : RawByteString;cp : TSystemCodePage);[Public,Alias : 'FPC_ANSISTR_LONGWORD']; compilerproc; inline;
  1034. Var
  1035. SS : ShortString;
  1036. begin
  1037. str(v:Len,SS);
  1038. S:=SS;
  1039. SetCodePage(s,cp,false);
  1040. end;
  1041. Procedure fpc_AnsiStr_LongInt(v : LongInt; Len : SizeInt; out S : RawByteString;cp : TSystemCodePage);[Public,Alias : 'FPC_ANSISTR_LONGINT']; compilerproc; inline;
  1042. Var
  1043. SS : ShortString;
  1044. begin
  1045. str (v:Len,SS);
  1046. S:=SS;
  1047. SetCodePage(s,cp,false);
  1048. end;
  1049. Procedure fpc_AnsiStr_Word(v : Word;Len : SizeInt; out S : RawByteString;cp : TSystemCodePage);[Public,Alias : 'FPC_ANSISTR_WORD']; compilerproc; inline;
  1050. Var
  1051. SS : ShortString;
  1052. begin
  1053. str(v:Len,SS);
  1054. S:=SS;
  1055. SetCodePage(s,cp,false);
  1056. end;
  1057. Procedure fpc_AnsiStr_SmallInt(v : SmallInt; Len : SizeInt; out S : RawByteString;cp : TSystemCodePage);[Public,Alias : 'FPC_ANSISTR_SMALLINT']; compilerproc; inline;
  1058. Var
  1059. SS : ShortString;
  1060. begin
  1061. str (v:Len,SS);
  1062. S:=SS;
  1063. SetCodePage(s,cp,false);
  1064. end;
  1065. {$endif CPU16 or CPU8}
  1066. Procedure fpc_ansistr_delete(Var S : RawByteString; Index,Size: SizeInt);
  1067. Var
  1068. LS : SizeInt;
  1069. begin
  1070. ls:=Length(S);
  1071. If (Index>LS) or (Index<=0) or (Size<=0) then
  1072. exit;
  1073. UniqueString(S);
  1074. If (Size>LS-Index) then // Size+Index gives overflow ??
  1075. Size:=LS-Index+1;
  1076. If (Size<=LS-Index) then
  1077. begin
  1078. Dec(Index);
  1079. fpc_pchar_ansistr_intern_charmove(PAnsiChar(S),Index+Size,S,Index,LS-Index-Size+1);
  1080. end;
  1081. Setlength(S,LS-Size);
  1082. end;
  1083. Procedure fpc_ansistr_insert(Const Source : RawByteString; Var S : RawByteString; Index : SizeInt);
  1084. var
  1085. LS,LSource : SizeInt;
  1086. {$ifdef jvm}
  1087. Temp : RawByteString;
  1088. {$else}
  1089. selfinsert : boolean;
  1090. srcp : PAnsiChar;
  1091. {$endif}
  1092. begin
  1093. If Source='' then
  1094. exit;
  1095. if S='' then
  1096. begin
  1097. S:=Source;
  1098. exit;
  1099. end;
  1100. LSource:={$ifdef jvm}Length(Source){$else}PAnsiRec(Pointer(Source)-AnsiFirstOff)^.Len{$endif};
  1101. LS:={$ifdef jvm}Length(S){$else}PAnsiRec(Pointer(S)-AnsiFirstOff)^.Len{$endif};
  1102. if index < 1 then
  1103. index := 1;
  1104. Dec(Index);
  1105. if index > LS then
  1106. index := LS;
  1107. {$ifdef jvm}
  1108. SetLength(Temp,LSource+LS);
  1109. SetCodePage(Temp,StringCodePage(S),false);
  1110. If Index>0 then
  1111. fpc_pchar_ansistr_intern_charmove(PAnsiChar(S),0,Temp,0,Index);
  1112. fpc_pchar_ansistr_intern_charmove(PAnsiChar(Source),0,Temp,Index,LSource);
  1113. If (LS-Index)>0 then
  1114. fpc_pchar_ansistr_intern_charmove(PAnsiChar(S),Index,Temp,LSource+Index,LS-Index);
  1115. S:=Temp;
  1116. {$else}
  1117. selfinsert:=Pointer(Source)=Pointer(S);
  1118. SetLength(S,LS+LSource);
  1119. Move(PAnsiChar(Pointer(S))[Index],PAnsiChar(Pointer(S))[Index+LSource],(LS-Index)*SizeOf(AnsiChar));
  1120. srcp:=Pointer(Source);
  1121. if selfinsert then
  1122. srcp:=Pointer(S);
  1123. Move(srcp^,PAnsiChar(Pointer(S))[Index],LSource*SizeOf(AnsiChar));
  1124. {$endif}
  1125. end;
  1126. {$ifndef FPC_HAS_ANSISTR_OF_CHAR}
  1127. {$define FPC_HAS_ANSISTR_OF_CHAR}
  1128. Function StringOfChar(c : Ansichar;l : SizeInt) : AnsiString;
  1129. begin
  1130. SetLength(StringOfChar,l);
  1131. FillChar(Pointer(StringOfChar)^,Length(StringOfChar),c);
  1132. end;
  1133. {$endif FPC_HAS_ANSISTR_OF_CHAR}
  1134. Procedure fpc_setstring_ansistr_pansichar(out S : RawByteString; Buf : PAnsiChar; Len : SizeInt; cp: TSystemCodePage); rtlproc; compilerproc;
  1135. begin
  1136. SetLength(S,Len);
  1137. SetCodePage(S,cp,false);
  1138. If (Buf<>Nil) then
  1139. fpc_pchar_ansistr_intern_charmove(Buf,0,S,0,Len);
  1140. end;
  1141. Procedure fpc_setstring_ansistr_pwidechar(out S : RawByteString; Buf : PWideChar; Len : SizeInt; cp: TSystemCodePage); rtlproc; compilerproc;
  1142. begin
  1143. cp:=TranslatePlaceholderCP(cp);
  1144. if (Buf<>nil) and (Len>0) then
  1145. widestringmanager.Wide2AnsiMoveProc(Buf,S,cp,Len)
  1146. else
  1147. begin
  1148. SetLength(S, Len);
  1149. SetCodePage(S,cp,false);
  1150. end;
  1151. end;
  1152. {$ifndef FPC_HAS_UPCASE_ANSISTR}
  1153. {$define FPC_HAS_UPCASE_ANSISTR}
  1154. function upcase(const s : ansistring) : ansistring;
  1155. var
  1156. i : SizeInt;
  1157. begin
  1158. Setlength(result,length(s));
  1159. for i := 1 to length (s) do
  1160. result[i] := upcase(s[i]);
  1161. end;
  1162. {$endif FPC_HAS_UPCASE_ANSISTR}
  1163. {$ifndef FPC_HAS_LOWERCASE_ANSISTR}
  1164. {$define FPC_HAS_LOWERCASE_ANSISTR}
  1165. function lowercase(const s : ansistring) : ansistring;
  1166. var
  1167. i : SizeInt;
  1168. begin
  1169. Setlength(result,length(s));
  1170. for i := 1 to length (s) do
  1171. result[i] := lowercase(s[i]);
  1172. end;
  1173. {$endif FPC_HAS_LOWERCASE_ANSISTR}
  1174. {$ifndef FPC_HAS_ANSISTR_STRINGCODEPAGE}
  1175. {$define FPC_HAS_ANSISTR_STRINGCODEPAGE}
  1176. function StringCodePage(const S: RawByteString): TSystemCodePage; overload;
  1177. begin
  1178. if assigned(Pointer(S)) then
  1179. Result:=PAnsiRec(pointer(S)-AnsiFirstOff)^.CodePage
  1180. else
  1181. Result:=DefaultSystemCodePage;
  1182. end;
  1183. {$endif FPC_HAS_ANSISTR_STRINGCODEPAGE}
  1184. {$ifndef FPC_HAS_ANSISTR_STRINGELEMENTSIZE}
  1185. {$define FPC_HAS_ANSISTR_STRINGELEMENTSIZE}
  1186. function StringElementSize(const S: RawByteString): Word; overload;
  1187. begin
  1188. if assigned(Pointer(S)) then
  1189. Result:=PAnsiRec(pointer(S)-AnsiFirstOff)^.ElementSize
  1190. else
  1191. Result:=SizeOf(AnsiChar);
  1192. end;
  1193. {$endif FPC_HAS_ANSISTR_STRINGELEMENTSIZE}
  1194. {$ifndef FPC_HAS_ANSISTR_STRINGREFCOUNT}
  1195. {$define FPC_HAS_ANSISTR_STRINGREFCOUNT}
  1196. function StringRefCount(const S: RawByteString): SizeInt; overload;
  1197. begin
  1198. if assigned(Pointer(S)) then
  1199. Result:=PAnsiRec(pointer(S)-AnsiFirstOff)^.Ref
  1200. else
  1201. Result:=0;
  1202. end;
  1203. {$endif FPC_HAS_ANSISTR_STRINGREFCOUNT}
  1204. {$ifndef FPC_HAS_ANSISTR_SETCODEPAGE}
  1205. {$define FPC_HAS_ANSISTR_SETCODEPAGE}
  1206. procedure InternalSetCodePage(var s : RawByteString; CodePage : TSystemCodePage; Convert : Boolean = True);
  1207. begin
  1208. if Convert then
  1209. begin
  1210. s:=fpc_AnsiStr_To_AnsiStr(s,CodePage);
  1211. end
  1212. else
  1213. begin
  1214. UniqueString(s);
  1215. PAnsiRec(pointer(s)-AnsiFirstOff)^.CodePage:=CodePage;
  1216. end;
  1217. end;
  1218. { use this wrapper for the simple case to avoid the generation of a temp. ansistring which causes
  1219. extra exception frames }
  1220. procedure SetCodePage(var s : RawByteString; CodePage : TSystemCodePage; Convert : Boolean = True);
  1221. var
  1222. OrgCodePage,
  1223. TranslatedCodePage,
  1224. TranslatedCurrentCodePage: TSystemCodePage;
  1225. begin
  1226. if Length(S)=0 then
  1227. exit;
  1228. { if the codepage are identical, we don't have to do anything (even if the
  1229. string has multiple references) }
  1230. OrgCodePage:=PAnsiRec(pointer(S)-AnsiFirstOff)^.CodePage;
  1231. if OrgCodePage=CodePage then
  1232. exit;
  1233. { if we're just replacing a placeholder code page with its actual value or
  1234. vice versa, we don't have to perform any conversion }
  1235. TranslatedCurrentCodePage:=TranslatePlaceholderCP(OrgCodePage);
  1236. TranslatedCodePage:=TranslatePlaceholderCP(CodePage);
  1237. Convert:=Convert and
  1238. (TranslatedCurrentCodePage<>TranslatedCodePage);
  1239. if not Convert and (PAnsiRec(pointer(S)-AnsiFirstOff)^.Ref=1) then
  1240. PAnsiRec(pointer(S)-AnsiFirstOff)^.CodePage:=CodePage
  1241. else
  1242. InternalSetCodePage(S,CodePage,Convert);
  1243. end;
  1244. {$endif FPC_HAS_ANSISTR_SETCODEPAGE}
  1245. procedure SetMultiByteConversionCodePage(CodePage: TSystemCodePage);
  1246. begin
  1247. DefaultSystemCodePage:=CodePage;
  1248. end;
  1249. procedure SetMultiByteFileSystemCodePage(CodePage: TSystemCodePage);
  1250. begin
  1251. DefaultFileSystemCodePage:=CodePage;
  1252. end;
  1253. procedure SetMultiByteRTLFileSystemCodePage(CodePage: TSystemCodePage);
  1254. begin
  1255. DefaultRTLFileSystemCodePage:=CodePage;
  1256. end;