astrings.inc 45 KB

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