astrings.inc 45 KB

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