astrings.inc 46 KB

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