astrings.inc 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251
  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. {
  15. This file contains the implementation of the AnsiString type,
  16. and all things that are needed for it.
  17. AnsiString is defined as a 'silent' pchar :
  18. a pchar that points to :
  19. @-8 : SizeInt for reference count;
  20. @-4 : SizeInt for size;
  21. @ : String + Terminating #0;
  22. Pchar(Ansistring) is a valid typecast.
  23. So AS[i] is converted to the address @AS+i-1.
  24. Constants should be assigned a reference count of -1
  25. Meaning that they can't be disposed of.
  26. }
  27. Type
  28. PAnsiRec = ^TAnsiRec;
  29. TAnsiRec = Packed Record
  30. CodePage : TSystemCodePage;
  31. ElementSize : Word;
  32. {$ifdef CPU64}
  33. { align fields }
  34. Dummy : DWord;
  35. {$endif CPU64}
  36. Ref : SizeInt;
  37. Len : SizeInt;
  38. First : AnsiChar;
  39. end;
  40. Const
  41. AnsiRecLen = SizeOf(TAnsiRec);
  42. AnsiFirstOff = SizeOf(TAnsiRec)-1;
  43. {****************************************************************************
  44. Internal functions, not in interface.
  45. ****************************************************************************}
  46. Function NewAnsiString(Len : SizeInt) : Pointer;
  47. {
  48. Allocate a new AnsiString on the heap.
  49. initialize it to zero length and reference count 1.
  50. }
  51. Var
  52. P : Pointer;
  53. begin
  54. { request a multiple of 16 because the heap manager alloctes anyways chunks of 16 bytes }
  55. GetMem(P,Len+AnsiRecLen);
  56. If P<>Nil then
  57. begin
  58. PAnsiRec(P)^.Ref:=1; { Set reference count }
  59. PAnsiRec(P)^.Len:=0; { Initial length }
  60. PAnsiRec(P)^.CodePage:=DefaultSystemCodePage;
  61. PAnsiRec(P)^.ElementSize:=SizeOf(AnsiChar);
  62. PAnsiRec(P)^.First:=#0; { Terminating #0 }
  63. inc(p,AnsiFirstOff); { Points to string now }
  64. end;
  65. NewAnsiString:=P;
  66. end;
  67. {$ifndef FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  68. Procedure fpc_ansistr_decr_ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DECR_REF']; compilerproc;
  69. {
  70. Decreases the ReferenceCount of a non constant ansistring;
  71. If the reference count is zero, deallocate the string;
  72. }
  73. Var
  74. p: PAnsiRec;
  75. Begin
  76. { Zero string }
  77. If S=Nil then
  78. exit;
  79. { check for constant strings ...}
  80. p:=PAnsiRec(S-AnsiFirstOff);
  81. If p^.ref<0 then exit;
  82. { declocked does a MT safe dec and returns true, if the counter is 0 }
  83. If declocked(p^.ref) then
  84. begin
  85. FreeMem(p);
  86. s:=nil;
  87. end;
  88. end;
  89. {$endif FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
  90. { also define alias for internal use in the system unit }
  91. Procedure fpc_ansistr_decr_ref (Var S : Pointer); [external name 'FPC_ANSISTR_DECR_REF'];
  92. Procedure fpc_AnsiStr_Incr_Ref (S : Pointer); [Public,Alias:'FPC_ANSISTR_INCR_REF']; compilerproc; {$IFNDEF VER2_0} Inline; {$ENDIF}
  93. Begin
  94. If S=Nil then
  95. exit;
  96. { Let's be paranoid : Constant string ??}
  97. If PAnsiRec(S-AnsiFirstOff)^.Ref<0 then exit;
  98. inclocked(PAnsiRec(S-AnsiFirstOff)^.Ref);
  99. end;
  100. { also define alias which can be used inside the system unit }
  101. Procedure fpc_AnsiStr_Incr_Ref (S : Pointer); [external name 'FPC_ANSISTR_INCR_REF'];
  102. Procedure fpc_AnsiStr_Assign (Var DestS : Pointer;S2 : Pointer);[Public,Alias:'FPC_ANSISTR_ASSIGN']; compilerproc;
  103. {
  104. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  105. }
  106. begin
  107. if DestS=S2 then
  108. exit;
  109. If S2<>nil then
  110. If PAnsiRec(S2-AnsiFirstOff)^.Ref>0 then
  111. inclocked(PAnsiRec(S2-AnsiFirstOff)^.Ref);
  112. { Decrease the reference count on the old S1 }
  113. fpc_ansistr_decr_ref (DestS);
  114. { And finally, have DestS pointing to S2 (or its copy) }
  115. DestS:=S2;
  116. end;
  117. { alias for internal use }
  118. Procedure fpc_AnsiStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_ANSISTR_ASSIGN'];
  119. procedure fpc_AnsiStr_Concat (var DestS:RawByteString;const S1,S2 : RawByteString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc;
  120. Var
  121. Size,Location : SizeInt;
  122. same : boolean;
  123. S1CP, S2CP, DestCP: TSystemCodePage;
  124. U: UnicodeString;
  125. begin
  126. { if codepages are differ then concat using unicodestring }
  127. S1CP:=StringCodePage(S1);
  128. if (S1CP=CP_ACP) then
  129. S1CP:=DefaultSystemCodePage;
  130. S2CP:=StringCodePage(S2);
  131. if (S2CP=CP_ACP) then
  132. S2CP:=DefaultSystemCodePage;
  133. {$ifdef FPC_HAS_CPSTRING}
  134. if (Pointer(DestS)=nil) then
  135. DestCP:=cp
  136. else
  137. DestCP:=StringCodePage(DestS);
  138. {$else FPC_HAS_CPSTRING}
  139. DestCP:=StringCodePage(DestS);
  140. {$endif FPC_HAS_CPSTRING}
  141. if (DestCP=CP_ACP) then
  142. DestCP:=DefaultSystemCodePage;
  143. if (S1CP<>DestCP) or (S2CP<>DestCP) then
  144. begin
  145. U:=UnicodeString(S1)+UnicodeString(S2);
  146. DestS:='';
  147. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(U)),DestS,DestCP,Length(U));
  148. exit;
  149. end;
  150. { only assign if s1 or s2 is empty }
  151. if (S1='') then
  152. begin
  153. DestS:=s2;
  154. exit;
  155. end;
  156. if (S2='') then
  157. begin
  158. DestS:=s1;
  159. exit;
  160. end;
  161. Location:=Length(S1);
  162. Size:=length(S2);
  163. { Use Pointer() typecasts to prevent extra conversion code }
  164. if Pointer(DestS)=Pointer(S1) then
  165. begin
  166. same:=Pointer(S1)=Pointer(S2);
  167. SetLength(DestS,Size+Location);
  168. if same then
  169. Move(Pointer(DestS)^,(Pointer(DestS)+Location)^,Size)
  170. else
  171. Move(Pointer(S2)^,(Pointer(DestS)+Location)^,Size+1);
  172. end
  173. else if Pointer(DestS)=Pointer(S2) then
  174. begin
  175. SetLength(DestS,Size+Location);
  176. Move(Pointer(DestS)^,(Pointer(DestS)+Location)^,Size+1);
  177. Move(Pointer(S1)^,Pointer(DestS)^,Location);
  178. end
  179. else
  180. begin
  181. DestS:='';
  182. SetLength(DestS,Size+Location);
  183. Move(Pointer(S1)^,Pointer(DestS)^,Location);
  184. Move(Pointer(S2)^,(Pointer(DestS)+Location)^,Size+1);
  185. end;
  186. SetCodePage(DestS,DestCP,false);
  187. end;
  188. procedure fpc_AnsiStr_Concat_multi (var DestS:RawByteString;const sarr:array of RawByteString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc;
  189. Var
  190. lowstart,i : Longint;
  191. p,pc : pointer;
  192. Size,NewLen,
  193. OldDestLen : SizeInt;
  194. destcopy : pointer;
  195. DestCP : TSystemCodePage;
  196. U : UnicodeString;
  197. sameCP : Boolean;
  198. tmpStr : RawByteString;
  199. tmpCP : TSystemCodePage;
  200. begin
  201. if high(sarr)=0 then
  202. begin
  203. DestS:='';
  204. exit;
  205. end;
  206. {$ifdef FPC_HAS_CPSTRING}
  207. if (Pointer(DestS)=nil) then
  208. DestCP:=cp
  209. else
  210. DestCP:=StringCodePage(DestS);
  211. {$else FPC_HAS_CPSTRING}
  212. DestCP:=StringCodePage(DestS);
  213. {$endif FPC_HAS_CPSTRING}
  214. if (DestCP=CP_ACP) then
  215. DestCP:=DefaultSystemCodePage;
  216. sameCP:=true;
  217. lowstart:=low(sarr);
  218. for i:=lowstart to high(sarr) do
  219. begin
  220. if (DestCP<>StringCodePage(sarr[i])) then
  221. begin
  222. sameCP:=false;
  223. break;
  224. end;
  225. end;
  226. if not sameCP then
  227. begin
  228. U:='';
  229. for i:=lowstart to high(sarr) do begin
  230. tmpCP:=StringCodePage(sarr[i]);
  231. if (tmpCP=CP_ACP) then
  232. begin
  233. tmpStr:=sarr[i];
  234. SetCodePage(tmpStr,DefaultSystemCodePage,False);
  235. U:=U+UnicodeString(tmpStr);
  236. end
  237. else
  238. U:=U+UnicodeString(sarr[i]);
  239. end;
  240. DestS:='';
  241. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(U)),DestS,DestCP,Length(U));
  242. exit;
  243. end;
  244. destcopy:=nil;
  245. lowstart:=low(sarr);
  246. if Pointer(DestS)=Pointer(sarr[lowstart]) then
  247. inc(lowstart);
  248. { Check for another reuse, then we can't use
  249. the append optimization }
  250. for i:=lowstart to high(sarr) do
  251. begin
  252. if Pointer(DestS)=Pointer(sarr[i]) then
  253. begin
  254. { if DestS is used somewhere in the middle of the expression,
  255. we need to make sure the original string still exists after
  256. we empty/modify DestS }
  257. destcopy:=pointer(dests);
  258. fpc_AnsiStr_Incr_Ref(destcopy);
  259. lowstart:=low(sarr);
  260. break;
  261. end;
  262. end;
  263. { Start with empty DestS if we start with concatting
  264. the first array element }
  265. if lowstart=low(sarr) then
  266. DestS:='';
  267. OldDestLen:=length(DestS);
  268. { Calculate size of the result so we can do
  269. a single call to SetLength() }
  270. NewLen:=0;
  271. for i:=low(sarr) to high(sarr) do
  272. inc(NewLen,length(sarr[i]));
  273. SetLength(DestS,NewLen);
  274. if (StringCodePage(DestS) <> DestCP) then
  275. SetCodePage(DestS,DestCP,False);
  276. { Concat all strings, except the string we already
  277. copied in DestS }
  278. pc:=Pointer(DestS)+OldDestLen;
  279. for i:=lowstart to high(sarr) do
  280. begin
  281. p:=pointer(sarr[i]);
  282. if assigned(p) then
  283. begin
  284. Size:=length(ansistring(p));
  285. Move(p^,pc^,Size+1);
  286. inc(pc,size);
  287. end;
  288. end;
  289. fpc_AnsiStr_Decr_Ref(destcopy);
  290. end;
  291. {$ifdef EXTRAANSISHORT}
  292. Procedure AnsiStr_ShortStr_Concat (Var S1: AnsiString; Var S2 : ShortString);
  293. {
  294. Concatenates a Ansi with a short string; : S2 + S2
  295. }
  296. Var
  297. Size,Location : SizeInt;
  298. begin
  299. Size:=Length(S2);
  300. Location:=Length(S1);
  301. If Size=0 then
  302. exit;
  303. { Setlength takes case of uniqueness
  304. and alllocated memory. We need to use length,
  305. to take into account possibility of S1=Nil }
  306. SetLength (S1,Size+Length(S1));
  307. Move (S2[1],Pointer(Pointer(S1)+Location)^,Size);
  308. PByte( Pointer(S1)+length(S1) )^:=0; { Terminating Zero }
  309. end;
  310. {$endif EXTRAANSISHORT}
  311. {$ifdef FPC_HAS_CPSTRING}
  312. Function fpc_AnsiStr_To_AnsiStr (const S : RawByteString;cp : TSystemCodePage): RawByteString; [Public, alias: 'FPC_ANSISTR_TO_ANSISTR']; compilerproc;
  313. {
  314. Converts an AnsiString to an AnsiString taking code pages into care
  315. }
  316. Var
  317. Size : SizeInt;
  318. temp : UnicodeString;
  319. orgcp: TSystemCodePage;
  320. begin
  321. result:='';
  322. Size:=Length(S);
  323. if Size>0 then
  324. begin
  325. if (cp=CP_ACP) then
  326. cp:=DefaultSystemCodePage;
  327. orgcp:=StringCodePage(S);
  328. if (orgcp=CP_ACP) then
  329. orgcp:=DefaultSystemCodePage;
  330. if (orgcp=cp) or (orgcp=CP_NONE) then
  331. begin
  332. SetLength(result,Size);
  333. Move(S[1],result[1],Size);
  334. PAnsiRec(Pointer(result)-AnsiFirstOff)^.CodePage:=cp;
  335. end
  336. else
  337. begin
  338. temp:=S;
  339. Size:=Length(temp);
  340. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(temp)),result,cp,Size);
  341. end;
  342. end;
  343. end;
  344. Function fpc_AnsiStr_To_AnsiStr (const S : RawByteString;cp : TSystemCodePage): RawByteString; [external name 'FPC_ANSISTR_TO_ANSISTR'];
  345. {$endif FPC_HAS_CPSTRING}
  346. procedure fpc_AnsiStr_To_ShortStr (out res: shortstring; const S2 : RawByteString);[Public, alias: 'FPC_ANSISTR_TO_SHORTSTR']; compilerproc;
  347. {
  348. Converts a AnsiString to a ShortString;
  349. }
  350. Var
  351. Size : SizeInt;
  352. begin
  353. if S2='' then
  354. res:=''
  355. else
  356. begin
  357. Size:=Length(S2);
  358. If Size>high(res) then
  359. Size:=high(res);
  360. Move (S2[1],res[1],Size);
  361. byte(res[0]):=byte(Size);
  362. end;
  363. end;
  364. Function fpc_ShortStr_To_AnsiStr (Const S2 : ShortString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): RawByteString; compilerproc;
  365. {
  366. Converts a ShortString to a AnsiString;
  367. }
  368. Var
  369. Size : SizeInt;
  370. {$ifndef FPC_HAS_CPSTRING}
  371. cp : TSystemCodePage;
  372. {$endif FPC_HAS_CPSTRING}
  373. begin
  374. {$ifdef FPC_HAS_CPSTRING}
  375. if (cp=CP_ACP) then
  376. cp:=DefaultSystemCodePage;
  377. {$else FPC_HAS_CPSTRING}
  378. cp:=DefaultSystemCodePage;
  379. {$endif FPC_HAS_CPSTRING}
  380. Size:=Length(S2);
  381. Setlength(fpc_ShortStr_To_AnsiStr,Size);
  382. if Size>0 then
  383. begin
  384. Move(S2[1],Pointer(fpc_ShortStr_To_AnsiStr)^,Size);
  385. SetCodePage(fpc_ShortStr_To_AnsiStr,cp,False);
  386. end
  387. end;
  388. Function fpc_Char_To_AnsiStr(const c : AnsiChar{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): RawByteString; compilerproc;
  389. {
  390. Converts a Char to a AnsiString;
  391. }
  392. {$ifndef FPC_HAS_CPSTRING}
  393. var
  394. cp : TSystemCodePage;
  395. {$endif FPC_HAS_CPSTRING}
  396. begin
  397. {$ifdef FPC_HAS_CPSTRING}
  398. if (cp=CP_ACP) then
  399. cp:=DefaultSystemCodePage;
  400. {$else FPC_HAS_CPSTRING}
  401. cp:=DefaultSystemCodePage;
  402. {$endif FPC_HAS_CPSTRING}
  403. Setlength (fpc_Char_To_AnsiStr,1);
  404. PByte(Pointer(fpc_Char_To_AnsiStr))^:=byte(c);
  405. { Terminating Zero }
  406. PByte(Pointer(fpc_Char_To_AnsiStr)+1)^:=0;
  407. SetCodePage(fpc_Char_To_AnsiStr,cp,False);
  408. end;
  409. Function fpc_PChar_To_AnsiStr(const p : PAnsiChar{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): RawByteString; compilerproc;
  410. Var
  411. L : SizeInt;
  412. {$ifndef FPC_HAS_CPSTRING}
  413. cp : TSystemCodePage;
  414. {$endif FPC_HAS_CPSTRING}
  415. begin
  416. if (not assigned(p)) or (p[0]=#0) Then
  417. L := 0
  418. else
  419. l:=IndexChar(p^,-1,#0);
  420. SetLength(fpc_PChar_To_AnsiStr,L);
  421. if L > 0 then
  422. begin
  423. {$ifdef FPC_HAS_CPSTRING}
  424. if (cp=CP_ACP) then
  425. cp:=DefaultSystemCodePage;
  426. {$else FPC_HAS_CPSTRING}
  427. cp:=DefaultSystemCodePage;
  428. {$endif FPC_HAS_CPSTRING}
  429. Move (P[0],Pointer(fpc_PChar_To_AnsiStr)^,L);
  430. SetCodePage(fpc_PChar_To_AnsiStr,cp,False);
  431. end;
  432. end;
  433. 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;
  434. var
  435. i : SizeInt;
  436. {$ifndef FPC_HAS_CPSTRING}
  437. cp : TSystemCodePage;
  438. {$endif FPC_HAS_CPSTRING}
  439. begin
  440. if (zerobased) then
  441. begin
  442. if (arr[0]=#0) Then
  443. i := 0
  444. else
  445. begin
  446. i:=IndexChar(arr,high(arr)+1,#0);
  447. if i = -1 then
  448. i := high(arr)+1;
  449. end;
  450. end
  451. else
  452. i := high(arr)+1;
  453. SetLength(fpc_CharArray_To_AnsiStr,i);
  454. if i > 0 then
  455. begin
  456. {$ifdef FPC_HAS_CPSTRING}
  457. if (cp=CP_ACP) then
  458. cp:=DefaultSystemCodePage;
  459. {$else FPC_HAS_CPSTRING}
  460. cp:=DefaultSystemCodePage;
  461. {$endif FPC_HAS_CPSTRING}
  462. Move (arr[0],Pointer(fpc_CharArray_To_AnsiStr)^,i);
  463. SetCodePage(fpc_CharArray_To_AnsiStr,cp,False);
  464. end;
  465. end;
  466. procedure fpc_ansistr_to_chararray(out res: array of AnsiChar; const src: RawByteString); compilerproc;
  467. var
  468. len: SizeInt;
  469. begin
  470. len := length(src);
  471. if len > length(res) then
  472. len := length(res);
  473. {$push}{$r-}
  474. { make sure we don't try to access element 1 of the ansistring if it's nil }
  475. if len > 0 then
  476. move(src[1],res[0],len);
  477. fillchar(res[len],length(res)-len,0);
  478. {$pop}
  479. end;
  480. Function fpc_AnsiStr_Compare(const S1,S2 : RawByteString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE']; compilerproc;
  481. {
  482. Compares 2 AnsiStrings;
  483. The result is
  484. <0 if S1<S2
  485. 0 if S1=S2
  486. >0 if S1>S2
  487. }
  488. Var
  489. MaxI,Temp : SizeInt;
  490. cp1,cp2 : TSystemCodePage;
  491. r1,r2 : RawByteString;
  492. begin
  493. if pointer(S1)=pointer(S2) then
  494. begin
  495. result:=0;
  496. exit;
  497. end;
  498. if (pointer(S1)=nil) then
  499. begin
  500. result:=-Length(S2);
  501. exit;
  502. end;
  503. if (pointer(S2)=nil) then
  504. begin
  505. result:=Length(S1);
  506. exit;
  507. end;
  508. cp1:=StringCodePage(S1);
  509. cp2:=StringCodePage(S2);
  510. if (cp1=cp2) then
  511. begin
  512. Maxi:=Length(S1);
  513. temp:=Length(S2);
  514. If MaxI>Temp then
  515. MaxI:=Temp;
  516. if MaxI>0 then
  517. begin
  518. result:=CompareByte(S1[1],S2[1],MaxI);
  519. if result=0 then
  520. result:=Length(S1)-Length(S2);
  521. end
  522. else
  523. result:=Length(S1)-Length(S2);
  524. end
  525. else
  526. begin
  527. r1:=S1;
  528. if (cp1=CP_ACP) then
  529. SetCodePage(r1,DefaultSystemCodePage,false);
  530. r2:=S2;
  531. if (cp2=CP_ACP) then
  532. SetCodePage(r2,DefaultSystemCodePage,false);
  533. //convert them to utf8 then compare
  534. SetCodePage(r1,65001);
  535. SetCodePage(r2,65001);
  536. Result := fpc_AnsiStr_Compare(r1,r2);
  537. end;
  538. end;
  539. Function fpc_AnsiStr_Compare_equal(const S1,S2 : RawByteString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE_EQUAL']; compilerproc;
  540. {
  541. Compares 2 AnsiStrings for equality/inequality only;
  542. The result is
  543. 0 if S1=S2
  544. <>0 if S1<>S2
  545. }
  546. Var
  547. MaxI,Temp : SizeInt;
  548. cp1,cp2 : TSystemCodePage;
  549. r1,r2 : RawByteString;
  550. begin
  551. if pointer(S1)=pointer(S2) then
  552. begin
  553. result:=0;
  554. exit;
  555. end;
  556. { don't compare strings if one of them is empty }
  557. if (pointer(S1)=nil) then
  558. begin
  559. result:=-Length(S2);
  560. exit;
  561. end;
  562. if (pointer(S2)=nil) then
  563. begin
  564. result:=Length(S1);
  565. exit;
  566. end;
  567. cp1:=StringCodePage(S1);
  568. cp2:=StringCodePage(S2);
  569. if (cp1=cp2) then
  570. begin
  571. Maxi:=Length(S1);
  572. temp:=Length(S2);
  573. Result := Maxi - temp;
  574. if Result = 0 then
  575. if MaxI>0 then
  576. result:=CompareByte(S1[1],S2[1],MaxI);
  577. end
  578. else
  579. begin
  580. r1:=S1;
  581. if (cp1=CP_ACP) then
  582. SetCodePage(r1,DefaultSystemCodePage,false);
  583. r2:=S2;
  584. if (cp2=CP_ACP) then
  585. SetCodePage(r2,DefaultSystemCodePage,false);
  586. //convert them to utf8 then compare
  587. SetCodePage(r1,65001);
  588. SetCodePage(r2,65001);
  589. Maxi:=Length(r1);
  590. temp:=Length(r2);
  591. Result := Maxi - temp;
  592. if Result = 0 then
  593. if MaxI>0 then
  594. result:=CompareByte(r1[1],r2[1],MaxI);
  595. end;
  596. end;
  597. {$ifdef VER2_4}
  598. // obsolete but needed for boostrapping with 2.4
  599. Procedure fpc_AnsiStr_CheckZero(p : pointer);[Public,Alias : 'FPC_ANSISTR_CHECKZERO']; compilerproc;
  600. begin
  601. if p=nil then
  602. HandleErrorFrame(201,get_frame);
  603. end;
  604. Procedure fpc_AnsiStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_ANSISTR_RANGECHECK']; compilerproc;
  605. begin
  606. if (index>len) or (Index<1) then
  607. HandleErrorFrame(201,get_frame);
  608. end;
  609. {$else VER2_4}
  610. Procedure fpc_AnsiStr_CheckRange(p: Pointer; index: SizeInt);[Public,Alias : 'FPC_ANSISTR_RANGECHECK']; compilerproc;
  611. begin
  612. if (p=nil) or (index>PAnsiRec(p-AnsiFirstOff)^.Len) or (Index<1) then
  613. HandleErrorFrame(201,get_frame);
  614. end;
  615. {$endif VER2_4}
  616. 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;
  617. {
  618. Sets The length of string S to L.
  619. Makes sure S is unique, and contains enough room.
  620. }
  621. Var
  622. Temp : Pointer;
  623. lens, lena,
  624. movelen : SizeInt;
  625. begin
  626. if (l>0) then
  627. begin
  628. if Pointer(S)=nil then
  629. begin
  630. GetMem(Pointer(S),AnsiRecLen+L);
  631. PAnsiRec(S)^.Ref:=1;
  632. {$ifdef FPC_HAS_CPSTRING}
  633. if (cp=CP_ACP) then
  634. cp:=DefaultSystemCodePage;
  635. PAnsiRec(S)^.CodePage:=cp;
  636. {$else}
  637. PAnsiRec(S)^.CodePage:=DefaultSystemCodePage;
  638. {$endif FPC_HAS_CPSTRING}
  639. PAnsiRec(S)^.ElementSize:=1;
  640. inc(Pointer(S),AnsiFirstOff);
  641. end
  642. else if PAnsiRec(Pointer(S)-AnsiFirstOff)^.Ref=1 then
  643. begin
  644. Dec(Pointer(S),AnsiFirstOff);
  645. lens:=MemSize(Pointer(s));
  646. lena:=AnsiRecLen+L;
  647. { allow shrinking string if that saves at least half of current size }
  648. if (lena>lens) or ((lens>32) and (lena<=(lens div 2))) then
  649. reallocmem(pointer(S),AnsiRecLen+L);
  650. Inc(Pointer(S),AnsiFirstOff);
  651. end
  652. else
  653. begin
  654. { Reallocation is needed... }
  655. Temp:=Pointer(NewAnsiString(L));
  656. {$ifdef FPC_HAS_CPSTRING}
  657. PAnsiRec(Pointer(Temp)-AnsiFirstOff)^.CodePage:=cp;
  658. {$endif FPC_HAS_CPSTRING}
  659. { also move terminating null }
  660. lens:=succ(length(s));
  661. if l<lens then
  662. movelen:=l
  663. else
  664. movelen:=lens;
  665. Move(Pointer(S)^,Temp^,movelen);
  666. { ref count dropped to zero in the mean time? }
  667. If (PAnsiRec(Pointer(S)-AnsiFirstOff)^.Ref>0) and
  668. declocked(PAnsiRec(Pointer(S)-AnsiFirstOff)^.Ref) then
  669. freemem(PAnsiRec(Pointer(s)-AnsiFirstOff));
  670. Pointer(S):=Temp;
  671. end;
  672. { Force nil termination in case it gets shorter }
  673. PByte(Pointer(S)+l)^:=0;
  674. PAnsiRec(Pointer(S)-AnsiFirstOff)^.Len:=l;
  675. end
  676. else
  677. begin
  678. { Length=0 }
  679. if Pointer(S)<>nil then
  680. fpc_ansistr_decr_ref (Pointer(S));
  681. Pointer(S):=Nil;
  682. end;
  683. end;
  684. {$ifdef EXTRAANSISHORT}
  685. Function fpc_AnsiStr_ShortStr_Compare (Var S1 : Pointer; Var S2 : ShortString): SizeInt; compilerproc;
  686. {
  687. Compares a AnsiString with a ShortString;
  688. The result is
  689. <0 if S1<S2
  690. 0 if S1=S2
  691. >0 if S1>S2
  692. }
  693. Var
  694. i,MaxI,Temp : SizeInt;
  695. begin
  696. Temp:=0;
  697. i:=0;
  698. MaxI:=Length(AnsiString(S1));
  699. if MaxI>byte(S2[0]) then
  700. MaxI:=Byte(S2[0]);
  701. While (i<MaxI) and (Temp=0) do
  702. begin
  703. Temp:= PByte(S1+I)^ - Byte(S2[i+1]);
  704. inc(i);
  705. end;
  706. AnsiStr_ShortStr_Compare:=Temp;
  707. end;
  708. {$endif EXTRAANSISHORT}
  709. {*****************************************************************************
  710. Public functions, In interface.
  711. *****************************************************************************}
  712. function fpc_truely_ansistr_unique(Var S : Pointer): Pointer;
  713. Var
  714. SNew : Pointer;
  715. L : SizeInt;
  716. begin
  717. L:=PAnsiRec(Pointer(S)-AnsiFirstOff)^.len;
  718. SNew:=NewAnsiString (L);
  719. Move (Pointer(S)^,SNew^,L+1);
  720. PAnsiRec(SNew-AnsiFirstOff)^.len:=L;
  721. PAnsiRec(SNew-AnsiFirstOff)^.CodePage:=PAnsiRec(Pointer(S)-AnsiFirstOff)^.CodePage;
  722. fpc_ansistr_decr_ref (Pointer(S)); { Thread safe }
  723. pointer(S):=SNew;
  724. pointer(result):=SNew;
  725. end;
  726. {$ifndef FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  727. // MV: inline the basic checks for case that S is already unique.
  728. // Rest is too complex to inline, so factor that out as a call.
  729. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; compilerproc; {$IFNDEF VER2_0} Inline; {$ENDIF}
  730. {
  731. Make sure reference count of S is 1,
  732. using copy-on-write semantics.
  733. }
  734. begin
  735. pointer(result) := pointer(s);
  736. If Pointer(S)=Nil then
  737. exit;
  738. if PAnsiRec(Pointer(S)-AnsiFirstOff)^.Ref<>1 then
  739. result:=fpc_truely_ansistr_unique(s);
  740. end;
  741. {$endif FPC_SYSTEM_HAS_ANSISTR_UNIQUE}
  742. Function Fpc_Ansistr_Copy(Const S : RawByteString; Index,Size : SizeInt) : RawByteString;compilerproc;
  743. var
  744. ResultAddress : Pointer;
  745. begin
  746. ResultAddress:=Nil;
  747. dec(index);
  748. if Index < 0 then
  749. Index := 0;
  750. { Check Size. Accounts for Zero-length S, the double check is needed because
  751. Size can be maxint and will get <0 when adding index }
  752. if (Size>Length(S)) or
  753. (Index+Size>Length(S)) then
  754. Size:=Length(S)-Index;
  755. If Size>0 then
  756. begin
  757. If Index<0 Then
  758. Index:=0;
  759. ResultAddress:=Pointer(NewAnsiString (Size));
  760. if ResultAddress<>Nil then
  761. begin
  762. Move (Pointer(Pointer(S)+index)^,ResultAddress^,Size);
  763. PByte(ResultAddress+Size)^:=0;
  764. PAnsiRec(ResultAddress-AnsiFirstOff)^.Len:=Size;
  765. PAnsiRec(ResultAddress-AnsiFirstOff)^.CodePage:=PAnsiRec(Pointer(S)-AnsiFirstOff)^.CodePage;
  766. end;
  767. end;
  768. fpc_ansistr_decr_ref(Pointer(fpc_ansistr_copy));
  769. Pointer(fpc_ansistr_Copy):=ResultAddress;
  770. end;
  771. Function Pos(Const Substr : ShortString; Const Source : RawByteString) : SizeInt;
  772. var
  773. i,MaxLen : SizeInt;
  774. pc : PAnsiChar;
  775. begin
  776. Pos:=0;
  777. if Length(SubStr)>0 then
  778. begin
  779. MaxLen:=Length(source)-Length(SubStr);
  780. i:=0;
  781. pc:=@source[1];
  782. while (i<=MaxLen) do
  783. begin
  784. inc(i);
  785. if (SubStr[1]=pc^) and
  786. (CompareByte(Substr[1],pc^,Length(SubStr))=0) then
  787. begin
  788. Pos:=i;
  789. exit;
  790. end;
  791. inc(pc);
  792. end;
  793. end;
  794. end;
  795. Function Pos(Const Substr : RawByteString; Const Source : RawByteString) : SizeInt;
  796. var
  797. i,MaxLen : SizeInt;
  798. pc : PAnsiChar;
  799. begin
  800. Pos:=0;
  801. if Length(SubStr)>0 then
  802. begin
  803. MaxLen:=Length(source)-Length(SubStr);
  804. i:=0;
  805. pc:=@source[1];
  806. while (i<=MaxLen) do
  807. begin
  808. inc(i);
  809. if (SubStr[1]=pc^) and
  810. (CompareByte(Substr[1],pc^,Length(SubStr))=0) then
  811. begin
  812. Pos:=i;
  813. exit;
  814. end;
  815. inc(pc);
  816. end;
  817. end;
  818. end;
  819. { Faster version for a char alone. Must be implemented because }
  820. { pos(c: char; const s: shortstring) also exists, so otherwise }
  821. { using pos(char,pchar) will always call the shortstring version }
  822. { (exact match for first argument), also with $h+ (JM) }
  823. Function Pos(c : AnsiChar; Const s : RawByteString) : SizeInt;
  824. var
  825. i: SizeInt;
  826. pc : PAnsiChar;
  827. begin
  828. pc:=@s[1];
  829. for i:=1 to length(s) do
  830. begin
  831. if pc^=c then
  832. begin
  833. pos:=i;
  834. exit;
  835. end;
  836. inc(pc);
  837. end;
  838. pos:=0;
  839. end;
  840. {$ifndef FPUNONE}
  841. Function fpc_Val_Real_AnsiStr(Const S : RawByteString; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_ANSISTR']; compilerproc;
  842. Var
  843. SS : String;
  844. begin
  845. fpc_Val_Real_AnsiStr := 0;
  846. if length(S) > 255 then
  847. code := 256
  848. else
  849. begin
  850. SS := S;
  851. Val(SS,fpc_Val_Real_AnsiStr,code);
  852. end;
  853. end;
  854. {$endif}
  855. Function fpc_Val_Currency_AnsiStr(Const S : RawByteString; out Code : ValSInt): Currency; [public, alias:'FPC_VAL_CURRENCY_ANSISTR']; compilerproc;
  856. Var
  857. SS : String;
  858. begin
  859. if length(S) > 255 then
  860. begin
  861. fpc_Val_Currency_AnsiStr := 0;
  862. code := 256;
  863. end
  864. else
  865. begin
  866. SS := S;
  867. Val(SS,fpc_Val_Currency_AnsiStr,code);
  868. end;
  869. end;
  870. Function fpc_Val_UInt_AnsiStr (Const S : RawByteString; out Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_ANSISTR']; compilerproc;
  871. Var
  872. SS : ShortString;
  873. begin
  874. fpc_Val_UInt_AnsiStr := 0;
  875. if length(S) > 255 then
  876. code := 256
  877. else
  878. begin
  879. SS := S;
  880. Val(SS,fpc_Val_UInt_AnsiStr,code);
  881. end;
  882. end;
  883. Function fpc_Val_SInt_AnsiStr (DestSize: SizeInt; Const S : RawByteString; out Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_ANSISTR']; compilerproc;
  884. Var
  885. SS : ShortString;
  886. begin
  887. fpc_Val_SInt_AnsiStr:=0;
  888. if length(S)>255 then
  889. code:=256
  890. else
  891. begin
  892. SS := S;
  893. fpc_Val_SInt_AnsiStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  894. end;
  895. end;
  896. {$ifndef CPU64}
  897. Function fpc_Val_qword_AnsiStr (Const S : RawByteString; out Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_ANSISTR']; compilerproc;
  898. Var
  899. SS : ShortString;
  900. begin
  901. fpc_Val_qword_AnsiStr:=0;
  902. if length(S)>255 then
  903. code:=256
  904. else
  905. begin
  906. SS := S;
  907. Val(SS,fpc_Val_qword_AnsiStr,Code);
  908. end;
  909. end;
  910. Function fpc_Val_int64_AnsiStr (Const S : RawByteString; out Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_ANSISTR']; compilerproc;
  911. Var
  912. SS : ShortString;
  913. begin
  914. fpc_Val_int64_AnsiStr:=0;
  915. if length(S)>255 then
  916. code:=256
  917. else
  918. begin
  919. SS := s;
  920. Val(SS,fpc_Val_int64_AnsiStr,Code);
  921. end;
  922. end;
  923. {$endif CPU64}
  924. {$ifndef FPUNONE}
  925. 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; {$IFNDEF VER2_0} Inline; {$ENDIF}
  926. var
  927. ss: ShortString;
  928. begin
  929. str_real(len,fr,d,treal_type(rt),ss);
  930. s:=ss;
  931. {$ifdef FPC_HAS_CPSTRING}
  932. SetCodePage(s,cp,false);
  933. {$endif FPC_HAS_CPSTRING}
  934. end;
  935. {$endif}
  936. 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; {$IFNDEF VER2_0} Inline; {$ENDIF}
  937. var ss:shortstring;
  938. begin
  939. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  940. s:=ss;
  941. {$ifdef FPC_HAS_CPSTRING}
  942. SetCodePage(s,cp,false);
  943. {$endif FPC_HAS_CPSTRING}
  944. end;
  945. 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; {$IFNDEF VER2_0} Inline; {$ENDIF}
  946. var
  947. ss:shortstring;
  948. begin
  949. fpc_shortstr_bool(b,len,ss);
  950. s:=ss;
  951. {$ifdef FPC_HAS_CPSTRING}
  952. SetCodePage(s,cp,false);
  953. {$endif FPC_HAS_CPSTRING}
  954. end;
  955. function fpc_val_enum_ansistr(str2ordindex:pointer;const s:RawByteString;out code:valsint):longint; [public, alias:'FPC_VAL_ENUM_ANSISTR']; compilerproc;
  956. begin
  957. fpc_val_enum_ansistr:=fpc_val_enum_shortstr(str2ordindex,s,code);
  958. end;
  959. {$ifdef FPC_HAS_STR_CURRENCY}
  960. 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; {$IFNDEF VER2_0} Inline; {$ENDIF}
  961. var
  962. ss: ShortString;
  963. begin
  964. str(c:len:fr,ss);
  965. s:=ss;
  966. {$ifdef FPC_HAS_CPSTRING}
  967. SetCodePage(s,cp,false);
  968. {$endif FPC_HAS_CPSTRING}
  969. end;
  970. {$endif FPC_HAS_STR_CURRENCY}
  971. 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; {$IFNDEF VER2_0} Inline; {$ENDIF}
  972. Var
  973. SS : ShortString;
  974. begin
  975. str(v:Len,SS);
  976. S:=SS;
  977. {$ifdef FPC_HAS_CPSTRING}
  978. SetCodePage(s,cp,false);
  979. {$endif FPC_HAS_CPSTRING}
  980. end;
  981. 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; {$IFNDEF VER2_0} Inline; {$ENDIF}
  982. Var
  983. SS : ShortString;
  984. begin
  985. str (v:Len,SS);
  986. S:=SS;
  987. {$ifdef FPC_HAS_CPSTRING}
  988. SetCodePage(s,cp,false);
  989. {$endif FPC_HAS_CPSTRING}
  990. end;
  991. {$ifndef CPU64}
  992. 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; {$IFNDEF VER2_0} Inline; {$ENDIF}
  993. Var
  994. SS : ShortString;
  995. begin
  996. str(v:Len,SS);
  997. S:=SS;
  998. {$ifdef FPC_HAS_CPSTRING}
  999. SetCodePage(s,cp,false);
  1000. {$endif FPC_HAS_CPSTRING}
  1001. end;
  1002. 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; {$IFNDEF VER2_0} Inline; {$ENDIF}
  1003. Var
  1004. SS : ShortString;
  1005. begin
  1006. str (v:Len,SS);
  1007. S:=SS;
  1008. {$ifdef FPC_HAS_CPSTRING}
  1009. SetCodePage(s,cp,false);
  1010. {$endif FPC_HAS_CPSTRING}
  1011. end;
  1012. {$endif CPU64}
  1013. Procedure Delete(Var S : RawByteString; Index,Size: SizeInt);
  1014. Var
  1015. LS : SizeInt;
  1016. begin
  1017. ls:=Length(S);
  1018. If (Index>LS) or (Index<=0) or (Size<=0) then
  1019. exit;
  1020. UniqueString(S);
  1021. If (Size>LS-Index) then // Size+Index gives overflow ??
  1022. Size:=LS-Index+1;
  1023. If (Size<=LS-Index) then
  1024. begin
  1025. Dec(Index);
  1026. Move(PByte(Pointer(S))[Index+Size],PByte(Pointer(S))[Index],LS-Index-Size+1);
  1027. end;
  1028. Setlength(S,LS-Size);
  1029. end;
  1030. Procedure Insert(Const Source : RawByteString; Var S : RawByteString; Index : SizeInt);
  1031. var
  1032. Temp : RawByteString;
  1033. LS : SizeInt;
  1034. cp : TSystemCodePage;
  1035. begin
  1036. If Length(Source)=0 then
  1037. exit;
  1038. if index <= 0 then
  1039. index := 1;
  1040. Ls:=Length(S);
  1041. if index > LS then
  1042. index := LS+1;
  1043. Dec(Index);
  1044. SetLength(Temp,Length(Source)+LS);
  1045. cp:=StringCodePage(S);
  1046. if (cp=CP_ACP) then
  1047. cp:=DefaultSystemCodePage;
  1048. SetCodePage(Temp,cp,false);
  1049. If Index>0 then
  1050. Move(Pointer(S)^,Pointer(Temp)^,Index);
  1051. Move(Pointer(Source)^,PByte(Temp)[Index],Length(Source));
  1052. If (LS-Index)>0 then
  1053. Move(PByte(Pointer(S))[Index],PByte(temp)[Length(Source)+index],LS-Index);
  1054. S:=Temp;
  1055. end;
  1056. Function StringOfChar(c : Ansichar;l : SizeInt) : AnsiString;
  1057. begin
  1058. SetLength(StringOfChar,l);
  1059. FillChar(Pointer(StringOfChar)^,Length(StringOfChar),c);
  1060. end;
  1061. Procedure SetString(Out S : AnsiString; Buf : PAnsiChar; Len : SizeInt); {$IFNDEF VER2_0} Inline; {$ENDIF}
  1062. begin
  1063. SetLength(S,Len);
  1064. If (Buf<>Nil) then
  1065. Move(Buf^,Pointer(S)^,Len);
  1066. end;
  1067. Procedure SetString(Out S : AnsiString; Buf : PWideChar; Len : SizeInt);
  1068. begin
  1069. if (Buf<>nil) and (Len>0) then
  1070. widestringmanager.Wide2AnsiMoveProc(Buf,S,DefaultSystemCodePage,Len)
  1071. else
  1072. SetLength(S, Len);
  1073. end;
  1074. function upcase(const s : ansistring) : ansistring;
  1075. var
  1076. i : SizeInt;
  1077. begin
  1078. Setlength(result,length(s));
  1079. for i := 1 to length (s) do
  1080. result[i] := upcase(s[i]);
  1081. end;
  1082. function lowercase(const s : ansistring) : ansistring;
  1083. var
  1084. i : SizeInt;
  1085. begin
  1086. Setlength(result,length(s));
  1087. for i := 1 to length (s) do
  1088. result[i] := lowercase(s[i]);
  1089. end;
  1090. function StringCodePage(const S: RawByteString): TSystemCodePage; overload;
  1091. begin
  1092. {$ifdef FPC_HAS_CPSTRING}
  1093. if assigned(Pointer(S)) then
  1094. Result:=PAnsiRec(pointer(S)-AnsiFirstOff)^.CodePage
  1095. else
  1096. {$endif FPC_HAS_CPSTRING}
  1097. Result:=DefaultSystemCodePage;
  1098. end;
  1099. function StringElementSize(const S: RawByteString): Word; overload;
  1100. begin
  1101. if assigned(Pointer(S)) then
  1102. Result:=PAnsiRec(pointer(S)-AnsiFirstOff)^.ElementSize
  1103. else
  1104. Result:=SizeOf(AnsiChar);
  1105. end;
  1106. function StringRefCount(const S: RawByteString): SizeInt; overload;
  1107. begin
  1108. if assigned(Pointer(S)) then
  1109. Result:=PAnsiRec(pointer(S)-AnsiFirstOff)^.Ref
  1110. else
  1111. Result:=0;
  1112. end;
  1113. procedure SetCodePage(var s : RawByteString; CodePage : TSystemCodePage; Convert : Boolean = True);
  1114. begin
  1115. if (S='') or (StringCodePage(S)=CodePage) then
  1116. exit
  1117. else if Convert then
  1118. begin
  1119. {$ifdef FPC_HAS_CPSTRING}
  1120. s:=fpc_AnsiStr_To_AnsiStr(s,CodePage);
  1121. {$else FPC_HAS_CPSTRING}
  1122. UniqueString(s);
  1123. PAnsiRec(pointer(s)-AnsiFirstOff)^.CodePage:=CodePage;
  1124. {$endif FPC_HAS_CPSTRING}
  1125. end
  1126. else
  1127. begin
  1128. UniqueString(s);
  1129. PAnsiRec(pointer(s)-AnsiFirstOff)^.CodePage:=CodePage;
  1130. end;
  1131. end;
  1132. procedure SetMultiByteConversionCodePage(CodePage: TSystemCodePage);
  1133. begin
  1134. DefaultSystemCodePage:=CodePage;
  1135. end;