astrings.inc 34 KB

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