astrings.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Michael Van Canneyt,
  5. member of the Free Pascal development team.
  6. This file implements AnsiStrings for FPC
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. { This will release some functions for special shortstring support }
  14. { define EXTRAANSISHORT}
  15. {
  16. This file contains the implementation of the AnsiString type,
  17. and all things that are needed for it.
  18. AnsiString is defined as a 'silent' pchar :
  19. a pchar that points to :
  20. @-8 : SizeInt for reference count;
  21. @-4 : SizeInt for size;
  22. @ : String + Terminating #0;
  23. Pchar(Ansistring) is a valid typecast.
  24. So AS[i] is converted to the address @AS+i-1.
  25. Constants should be assigned a reference count of -1
  26. Meaning that they can't be disposed of.
  27. }
  28. Type
  29. PAnsiRec = ^TAnsiRec;
  30. TAnsiRec = Packed Record
  31. Ref,
  32. Len : SizeInt;
  33. First : Char;
  34. end;
  35. Const
  36. AnsiRecLen = SizeOf(TAnsiRec);
  37. FirstOff = SizeOf(TAnsiRec)-1;
  38. {****************************************************************************
  39. Internal functions, not in interface.
  40. ****************************************************************************}
  41. Function NewAnsiString(Len : SizeInt) : Pointer;
  42. {
  43. Allocate a new AnsiString on the heap.
  44. initialize it to zero length and reference count 1.
  45. }
  46. Var
  47. P : Pointer;
  48. begin
  49. { request a multiple of 16 because the heap manager alloctes anyways chunks of 16 bytes }
  50. GetMem(P,Len+AnsiRecLen);
  51. If P<>Nil then
  52. begin
  53. PAnsiRec(P)^.Ref:=1; { Set reference count }
  54. PAnsiRec(P)^.Len:=0; { Initial length }
  55. PAnsiRec(P)^.First:=#0; { Terminating #0 }
  56. inc(p,firstoff); { Points to string now }
  57. end;
  58. NewAnsiString:=P;
  59. end;
  60. Procedure DisposeAnsiString(Var S : Pointer);
  61. {
  62. Deallocates a AnsiString From the heap.
  63. }
  64. begin
  65. If S=Nil then
  66. exit;
  67. Dec (S,FirstOff);
  68. FreeMem (S);
  69. S:=Nil;
  70. end;
  71. Procedure fpc_AnsiStr_Decr_Ref (Var S : Pointer);saveregisters;[Public,Alias:'FPC_ANSISTR_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  72. {
  73. Decreases the ReferenceCount of a non constant ansistring;
  74. If the reference count is zero, deallocate the string;
  75. }
  76. Type
  77. pSizeInt = ^SizeInt;
  78. Var
  79. l : pSizeInt;
  80. Begin
  81. { Zero string }
  82. If S=Nil then exit;
  83. { check for constant strings ...}
  84. l:=@PANSIREC(S-FirstOff)^.Ref;
  85. If l^<0 then exit;
  86. { declocked does a MT safe dec and returns true, if the counter is 0 }
  87. If declocked(l^) then
  88. { Ref count dropped to zero }
  89. DisposeAnsiString (S); { Remove...}
  90. {$ifndef decrrefnotnil}
  91. s:=nil;
  92. {$endif}
  93. end;
  94. {$ifdef hascompilerproc}
  95. { also define alias for internal use in the system unit }
  96. Procedure fpc_AnsiStr_Decr_Ref (Var S : Pointer);saveregisters; [external name 'FPC_ANSISTR_DECR_REF'];
  97. {$endif hascompilerproc}
  98. {$ifdef hascompilerproc}
  99. Procedure fpc_AnsiStr_Incr_Ref (S : Pointer);saveregisters;[Public,Alias:'FPC_ANSISTR_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  100. {$else}
  101. Procedure fpc_AnsiStr_Incr_Ref (Var S : Pointer);saveregisters;[Public,Alias:'FPC_ANSISTR_INCR_REF'];
  102. {$endif}
  103. Begin
  104. If S=Nil then
  105. exit;
  106. { Let's be paranoid : Constant string ??}
  107. If PAnsiRec(S-FirstOff)^.Ref<0 then exit;
  108. inclocked(PAnsiRec(S-FirstOff)^.Ref);
  109. end;
  110. {$ifdef hascompilerproc}
  111. { also define alias which can be used inside the system unit }
  112. Procedure fpc_AnsiStr_Incr_Ref (S : Pointer);saveregisters; [external name 'FPC_ANSISTR_INCR_REF'];
  113. {$endif hascompilerproc}
  114. Procedure fpc_AnsiStr_Assign (Var S1 : Pointer;S2 : Pointer);[Public,Alias:'FPC_ANSISTR_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
  115. {
  116. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  117. }
  118. begin
  119. If S2<>nil then
  120. If PAnsiRec(S2-FirstOff)^.Ref>0 then
  121. inclocked(PAnsiRec(S2-FirstOff)^.ref);
  122. { Decrease the reference count on the old S1 }
  123. fpc_ansistr_decr_ref (S1);
  124. { And finally, have S1 pointing to S2 (or its copy) }
  125. S1:=S2;
  126. end;
  127. {$ifdef hascompilerproc}
  128. { alias for internal use }
  129. Procedure fpc_AnsiStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_ANSISTR_ASSIGN'];
  130. {$endif hascompilerproc}
  131. {$ifdef hascompilerproc}
  132. function fpc_AnsiStr_Concat (const S1,S2 : AnsiString): ansistring; compilerproc;
  133. var
  134. S3: ansistring absolute result;
  135. {$else hascompilerproc}
  136. Procedure fpc_AnsiStr_Concat (const S1,S2 : ansistring;var S3 : ansistring);[Public, alias: 'FPC_ANSISTR_CONCAT'];
  137. {$endif hascompilerproc}
  138. {
  139. Concatenates 2 AnsiStrings : S1+S2.
  140. Result Goes to S3;
  141. }
  142. Var
  143. Size,Location : SizeInt;
  144. begin
  145. { only assign if s1 or s2 is empty }
  146. if (S1='') then
  147. s3 := s2
  148. else if (S2='') then
  149. s3 := s1
  150. else
  151. begin
  152. Size:=length(S2);
  153. Location:=Length(S1);
  154. SetLength (S3,Size+Location);
  155. { the cast to a pointer avoids the unique call }
  156. { and we don't need an unique call }
  157. { because of the SetLength S3 is unique }
  158. Move (S1[1],pointer(S3)^,Location);
  159. Move (S2[1],pointer(pointer(S3)+location)^,Size+1);
  160. end;
  161. end;
  162. {$ifdef EXTRAANSISHORT}
  163. Procedure AnsiStr_ShortStr_Concat (Var S1: AnsiString; Var S2 : ShortString);
  164. {
  165. Concatenates a Ansi with a short string; : S2 + S2
  166. }
  167. Var
  168. Size,Location : SizeInt;
  169. begin
  170. Size:=Length(S2);
  171. Location:=Length(S1);
  172. If Size=0 then
  173. exit;
  174. { Setlength takes case of uniqueness
  175. and alllocated memory. We need to use length,
  176. to take into account possibility of S1=Nil }
  177. SetLength (S1,Size+Length(S1));
  178. Move (S2[1],Pointer(Pointer(S1)+Location)^,Size);
  179. PByte( Pointer(S1)+length(S1) )^:=0; { Terminating Zero }
  180. end;
  181. {$endif EXTRAANSISHORT}
  182. { the following declaration has exactly the same effect as }
  183. { procedure fpc_AnsiStr_To_ShortStr (Var S1 : ShortString;S2 : Pointer); }
  184. { which is what the old helper was, so we don't need an extra implementation }
  185. { of the old helper (JM) }
  186. function fpc_AnsiStr_To_ShortStr (high_of_res: SizeInt;const S2 : Ansistring): shortstring;[Public, alias: 'FPC_ANSISTR_TO_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  187. {
  188. Converts a AnsiString to a ShortString;
  189. }
  190. Var
  191. Size : SizeInt;
  192. begin
  193. if S2='' then
  194. fpc_AnsiStr_To_ShortStr:=''
  195. else
  196. begin
  197. Size:=Length(S2);
  198. If Size>high_of_res then
  199. Size:=high_of_res;
  200. Move (S2[1],fpc_AnsiStr_To_ShortStr[1],Size);
  201. byte(fpc_AnsiStr_To_ShortStr[0]):=byte(Size);
  202. end;
  203. end;
  204. Function fpc_ShortStr_To_AnsiStr (Const S2 : ShortString): ansistring; {$ifdef hascompilerproc} compilerproc; {$endif}
  205. {
  206. Converts a ShortString to a AnsiString;
  207. }
  208. Var
  209. Size : SizeInt;
  210. begin
  211. Size:=Length(S2);
  212. Setlength (fpc_ShortStr_To_AnsiStr,Size);
  213. if Size>0 then
  214. Move(S2[1],Pointer(fpc_ShortStr_To_AnsiStr)^,Size);
  215. end;
  216. { old style helper }
  217. {$ifndef hascompilerproc}
  218. Procedure fpc_ShortStr_To_AnsiStr (Var S1 : Pointer; Const S2 : ShortString);[Public, alias: 'FPC_SHORTSTR_TO_ANSISTR'];
  219. begin
  220. s1 := pointer(fpc_ShortStr_To_AnsiStr(s2));
  221. end;
  222. {$endif hascompilerproc}
  223. Function fpc_Char_To_AnsiStr(const c : Char): AnsiString; {$ifdef hascompilerproc} compilerproc; {$endif}
  224. {
  225. Converts a Char to a AnsiString;
  226. }
  227. begin
  228. Setlength (fpc_Char_To_AnsiStr,1);
  229. PByte(Pointer(fpc_Char_To_AnsiStr))^:=byte(c);
  230. { Terminating Zero }
  231. PByte(Pointer(fpc_Char_To_AnsiStr)+1)^:=0;
  232. end;
  233. { old style helper }
  234. {$ifndef hascompilerproc}
  235. Procedure fpc_Char_To_AnsiStr(var S1 : Pointer; c : Char);[Public, alias: 'FPC_CHAR_TO_ANSISTR'];
  236. begin
  237. s1 := pointer(fpc_Char_To_AnsiStr(c));
  238. end;
  239. {$endif hascompilerproc}
  240. Function fpc_PChar_To_AnsiStr(const p : pchar): ansistring; {$ifdef hascompilerproc} compilerproc; {$endif}
  241. Var
  242. L : SizeInt;
  243. begin
  244. if (not assigned(p)) or (p[0]=#0) Then
  245. { result is automatically set to '' }
  246. exit;
  247. l:=IndexChar(p^,-1,#0);
  248. SetLength(fpc_PChar_To_AnsiStr,L);
  249. Move (P[0],Pointer(fpc_PChar_To_AnsiStr)^,L)
  250. end;
  251. { old style helper }
  252. {$ifndef hascompilerproc}
  253. Procedure fpc_PChar_To_AnsiStr(var a : ansistring;p : pchar);[Public,Alias : 'FPC_PCHAR_TO_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  254. begin
  255. pointer(a) := pointer(fpc_PChar_To_AnsiStr(p));
  256. end;
  257. {$endif hascompilerproc}
  258. Function fpc_CharArray_To_AnsiStr(const arr: array of char): ansistring; {$ifdef hascompilerproc} compilerproc; {$endif}
  259. var
  260. i : SizeInt;
  261. begin
  262. if arr[0]=#0 Then
  263. { result is automatically set to '' }
  264. exit;
  265. i:=IndexChar(arr,high(arr)+1,#0);
  266. if i = -1 then
  267. i := high(arr)+1;
  268. SetLength(fpc_CharArray_To_AnsiStr,i);
  269. Move (arr[0],Pointer(fpc_CharArray_To_AnsiStr)^,i);
  270. end;
  271. { old style helper }
  272. {$ifndef hascompilerproc}
  273. { the declaration below is the same as }
  274. { which is what the old helper was (we need the parameter as "array of char" type }
  275. { so we can pass it to the new style helper (JM) }
  276. Procedure fpc_CharArray_To_AnsiStr(var a : ansistring; p: pointer; len: SizeInt);[Public,Alias : 'FPC_CHARARRAY_TO_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  277. var
  278. src: pchar;
  279. i: SizeInt;
  280. begin
  281. src := pchar(p);
  282. if src[0]=#0 Then
  283. { result is automatically set to '' }
  284. begin
  285. pointer(a) := nil;
  286. exit;
  287. end;
  288. i:=IndexChar(src^,len,#0);
  289. if i = -1 then
  290. i := len;
  291. pointer(a) := NewAnsiString(i);
  292. Move (src^,a[1],i);
  293. end;
  294. {$endif not hascompilerproc}
  295. {$ifdef hascompilerproc}
  296. { note: inside the compiler, the resulttype is modified to be the length }
  297. { of the actual chararray to which we convert (JM) }
  298. function fpc_ansistr_to_chararray(arraysize: SizeInt; const src: ansistring): fpc_big_chararray; [public, alias: 'FPC_ANSISTR_TO_CHARARRAY']; compilerproc;
  299. var
  300. len: SizeInt;
  301. begin
  302. len := length(src);
  303. if len > arraysize then
  304. len := arraysize;
  305. { make sure we don't try to access element 1 of the ansistring if it's nil }
  306. if len > 0 then
  307. move(src[1],fpc_ansistr_to_chararray[0],len);
  308. fillchar(fpc_ansistr_to_chararray[len],arraysize-len,0);
  309. end;
  310. {$endif hascompilerproc}
  311. Function fpc_AnsiStr_Compare(const S1,S2 : AnsiString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  312. {
  313. Compares 2 AnsiStrings;
  314. The result is
  315. <0 if S1<S2
  316. 0 if S1=S2
  317. >0 if S1>S2
  318. }
  319. Var
  320. MaxI,Temp : SizeInt;
  321. begin
  322. if pointer(S1)=pointer(S2) then
  323. begin
  324. fpc_AnsiStr_Compare:=0;
  325. exit;
  326. end;
  327. Maxi:=Length(S1);
  328. temp:=Length(S2);
  329. If MaxI>Temp then
  330. MaxI:=Temp;
  331. Temp:=CompareByte(S1[1],S2[1],MaxI);
  332. if temp=0 then
  333. temp:=Length(S1)-Length(S2);
  334. fpc_AnsiStr_Compare:=Temp;
  335. end;
  336. Procedure fpc_AnsiStr_CheckZero(p : pointer);[Public,Alias : 'FPC_ANSISTR_CHECKZERO']; {$ifdef hascompilerproc} compilerproc; {$endif}
  337. begin
  338. if p=nil then
  339. HandleErrorFrame(201,get_frame);
  340. end;
  341. Procedure fpc_AnsiStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_ANSISTR_RANGECHECK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  342. begin
  343. if (index>len) or (Index<1) then
  344. HandleErrorFrame(201,get_frame);
  345. end;
  346. {$ifndef INTERNSETLENGTH}
  347. Procedure SetLength (Var S : AnsiString; l : SizeInt);
  348. {$else INTERNSETLENGTH}
  349. Procedure fpc_AnsiStr_SetLength (Var S : AnsiString; l : SizeInt);[Public,Alias : 'FPC_ANSISTR_SETLENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  350. {$endif INTERNSETLENGTH}
  351. {
  352. Sets The length of string S to L.
  353. Makes sure S is unique, and contains enough room.
  354. }
  355. Var
  356. Temp : Pointer;
  357. movelen : SizeInt;
  358. begin
  359. if (l>0) then
  360. begin
  361. if Pointer(S)=nil then
  362. begin
  363. { Need a complete new string...}
  364. Pointer(s):=NewAnsiString(l);
  365. end
  366. else if (PAnsiRec(Pointer(S)-FirstOff)^.Ref = 1) then
  367. begin
  368. Dec(Pointer(S),FirstOff);
  369. if AnsiRecLen+L>MemSize(Pointer(s)) then
  370. reallocmem(pointer(S),AnsiRecLen+L);
  371. Inc(Pointer(S),FirstOff);
  372. end
  373. else
  374. begin
  375. { Reallocation is needed... }
  376. Temp:=Pointer(NewAnsiString(L));
  377. if Length(S)>0 then
  378. begin
  379. if l < succ(length(s)) then
  380. movelen := l
  381. { also move terminating null }
  382. else movelen := succ(length(s));
  383. Move(Pointer(S)^,Temp^,movelen);
  384. end;
  385. fpc_ansistr_decr_ref(Pointer(S));
  386. Pointer(S):=Temp;
  387. end;
  388. { Force nil termination in case it gets shorter }
  389. PByte(Pointer(S)+l)^:=0;
  390. PAnsiRec(Pointer(S)-FirstOff)^.Len:=l;
  391. end
  392. else
  393. begin
  394. { Length=0 }
  395. if Pointer(S)<>nil then
  396. fpc_ansistr_decr_ref (Pointer(S));
  397. Pointer(S):=Nil;
  398. end;
  399. end;
  400. {$ifdef EXTRAANSISHORT}
  401. Function fpc_AnsiStr_ShortStr_Compare (Var S1 : Pointer; Var S2 : ShortString): SizeInt; {$ifdef hascompilerproc} compilerproc; {$endif}
  402. {
  403. Compares a AnsiString with a ShortString;
  404. The result is
  405. <0 if S1<S2
  406. 0 if S1=S2
  407. >0 if S1>S2
  408. }
  409. Var
  410. i,MaxI,Temp : SizeInt;
  411. begin
  412. Temp:=0;
  413. i:=0;
  414. MaxI:=Length(AnsiString(S1));
  415. if MaxI>byte(S2[0]) then
  416. MaxI:=Byte(S2[0]);
  417. While (i<MaxI) and (Temp=0) do
  418. begin
  419. Temp:= PByte(S1+I)^ - Byte(S2[i+1]);
  420. inc(i);
  421. end;
  422. AnsiStr_ShortStr_Compare:=Temp;
  423. end;
  424. {$endif EXTRAANSISHORT}
  425. {*****************************************************************************
  426. Public functions, In interface.
  427. *****************************************************************************}
  428. {$ifndef INTERNLENGTH}
  429. Function Length (Const S : AnsiString) : SizeInt;
  430. {
  431. Returns the length of an AnsiString.
  432. Takes in acount that zero strings are NIL;
  433. }
  434. begin
  435. If Pointer(S)=Nil then
  436. Length:=0
  437. else
  438. Length:=PAnsiRec(Pointer(S)-FirstOff)^.Len;
  439. end;
  440. {$endif INTERNLENGTH}
  441. {$ifdef HASCOMPILERPROC}
  442. { overloaded version of UniqueString for interface }
  443. Procedure UniqueString(Var S : AnsiString); [external name 'FPC_ANSISTR_UNIQUE'];
  444. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  445. {$else}
  446. Procedure UniqueString(Var S : AnsiString); [Public,Alias : 'FPC_ANSISTR_UNIQUE'];
  447. {$endif}
  448. {
  449. Make sure reference count of S is 1,
  450. using copy-on-write semantics.
  451. }
  452. Var
  453. SNew : Pointer;
  454. L : SizeInt;
  455. begin
  456. {$ifdef HASCOMPILERPROC}
  457. pointer(result) := pointer(s);
  458. {$endif}
  459. If Pointer(S)=Nil then
  460. exit;
  461. if PAnsiRec(Pointer(S)-Firstoff)^.Ref<>1 then
  462. begin
  463. L:=PAnsiRec(Pointer(S)-FirstOff)^.len;
  464. SNew:=NewAnsiString (L);
  465. Move (Pointer(S)^,SNew^,L+1);
  466. PAnsiRec(SNew-FirstOff)^.len:=L;
  467. fpc_ansistr_decr_ref (Pointer(S)); { Thread safe }
  468. pointer(S):=SNew;
  469. {$ifdef HASCOMPILERPROC}
  470. pointer(result):=SNew;
  471. {$endif}
  472. end;
  473. end;
  474. Procedure fpc_ansistr_append_char(Var S : AnsiString;c : char); [Public,Alias : 'FPC_ANSISTR_APPEND_CHAR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  475. begin
  476. SetLength(S,length(S)+1);
  477. S[length(S)]:=c;
  478. PByte(Pointer(S)+length(S))^:=0; { Terminating Zero }
  479. end;
  480. Procedure fpc_ansistr_append_shortstring(Var S : AnsiString;Str : ShortString); [Public,Alias : 'FPC_ANSISTR_APPEND_SHORTSTRING']; {$ifdef hascompilerproc} compilerproc; {$endif}
  481. var
  482. ofs : SizeInt;
  483. begin
  484. ofs:=Length(S);
  485. SetLength(S,ofs+length(Str));
  486. move(Str[1],S[ofs+1],length(Str));
  487. PByte(Pointer(S)+length(S))^:=0; { Terminating Zero }
  488. end;
  489. Procedure fpc_ansistr_append_ansistring(Var S : AnsiString;Str : AnsiString); [Public,Alias : 'FPC_ANSISTR_APPEND_ANSISTRING']; {$ifdef hascompilerproc} compilerproc; {$endif}
  490. var
  491. ofs : SizeInt;
  492. begin
  493. if Str<>'' then
  494. begin
  495. ofs:=Length(S);
  496. SetLength(S,ofs+length(Str));
  497. move(Str[1],S[ofs+1],length(Str)+1);
  498. end;
  499. end;
  500. {$ifdef interncopy}
  501. Function Fpc_Ansistr_Copy (Const S : AnsiString; Index,Size : SizeInt) : AnsiString;compilerproc;
  502. {$else}
  503. Function Copy (Const S : AnsiString; Index,Size : SizeInt) : AnsiString;
  504. {$endif}
  505. var
  506. ResultAddress : Pointer;
  507. begin
  508. ResultAddress:=Nil;
  509. dec(index);
  510. if Index < 0 then
  511. Index := 0;
  512. { Check Size. Accounts for Zero-length S, the double check is needed because
  513. Size can be maxint and will get <0 when adding index }
  514. if (Size>Length(S)) or
  515. (Index+Size>Length(S)) then
  516. Size:=Length(S)-Index;
  517. If Size>0 then
  518. begin
  519. If Index<0 Then
  520. Index:=0;
  521. ResultAddress:=Pointer(NewAnsiString (Size));
  522. if ResultAddress<>Nil then
  523. begin
  524. Move (Pointer(Pointer(S)+index)^,ResultAddress^,Size);
  525. PAnsiRec(ResultAddress-FirstOff)^.Len:=Size;
  526. PByte(ResultAddress+Size)^:=0;
  527. end;
  528. end;
  529. {$ifdef interncopy}
  530. Pointer(fpc_ansistr_Copy):=ResultAddress;
  531. {$else}
  532. Pointer(Copy):=ResultAddress;
  533. {$endif}
  534. end;
  535. Function Pos (Const Substr : AnsiString; Const Source : AnsiString) : SizeInt;
  536. var
  537. i,MaxLen : SizeInt;
  538. pc : pchar;
  539. begin
  540. Pos:=0;
  541. if Length(SubStr)>0 then
  542. begin
  543. MaxLen:=Length(source)-Length(SubStr);
  544. i:=0;
  545. pc:=@source[1];
  546. while (i<=MaxLen) do
  547. begin
  548. inc(i);
  549. if (SubStr[1]=pc^) and
  550. (CompareChar(Substr[1],pc^,Length(SubStr))=0) then
  551. begin
  552. Pos:=i;
  553. exit;
  554. end;
  555. inc(pc);
  556. end;
  557. end;
  558. end;
  559. { Faster version for a char alone. Must be implemented because }
  560. { pos(c: char; const s: shortstring) also exists, so otherwise }
  561. { using pos(char,pchar) will always call the shortstring version }
  562. { (exact match for first argument), also with $h+ (JM) }
  563. Function Pos (c : Char; Const s : AnsiString) : SizeInt;
  564. var
  565. i: SizeInt;
  566. pc : pchar;
  567. begin
  568. pc:=@s[1];
  569. for i:=1 to length(s) do
  570. begin
  571. if pc^=c then
  572. begin
  573. pos:=i;
  574. exit;
  575. end;
  576. inc(pc);
  577. end;
  578. pos:=0;
  579. end;
  580. Function fpc_Val_Real_AnsiStr(Const S : AnsiString; Var Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  581. Var
  582. SS : String;
  583. begin
  584. fpc_Val_Real_AnsiStr := 0;
  585. if length(S) > 255 then
  586. code := 256
  587. else
  588. begin
  589. SS := S;
  590. Val(SS,fpc_Val_Real_AnsiStr,code);
  591. end;
  592. end;
  593. Function fpc_Val_UInt_AnsiStr (Const S : AnsiString; Var Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  594. Var
  595. SS : ShortString;
  596. begin
  597. fpc_Val_UInt_AnsiStr := 0;
  598. if length(S) > 255 then
  599. code := 256
  600. else
  601. begin
  602. SS := S;
  603. Val(SS,fpc_Val_UInt_AnsiStr,code);
  604. end;
  605. end;
  606. Function fpc_Val_SInt_AnsiStr (DestSize: SizeInt; Const S : AnsiString; Var Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  607. Var
  608. SS : ShortString;
  609. begin
  610. fpc_Val_SInt_AnsiStr:=0;
  611. if length(S)>255 then
  612. code:=256
  613. else
  614. begin
  615. SS := S;
  616. fpc_Val_SInt_AnsiStr := fpc_Val_SInt_ShortStr(DestSize,SS,Code);
  617. end;
  618. end;
  619. {$ifndef CPU64}
  620. Function fpc_Val_qword_AnsiStr (Const S : AnsiString; Var Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  621. Var
  622. SS : ShortString;
  623. begin
  624. fpc_Val_qword_AnsiStr:=0;
  625. if length(S)>255 then
  626. code:=256
  627. else
  628. begin
  629. SS := S;
  630. Val(SS,fpc_Val_qword_AnsiStr,Code);
  631. end;
  632. end;
  633. Function fpc_Val_int64_AnsiStr (Const S : AnsiString; Var Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  634. Var
  635. SS : ShortString;
  636. begin
  637. fpc_Val_int64_AnsiStr:=0;
  638. if length(S)>255 then
  639. code:=256
  640. else
  641. begin
  642. SS := s;
  643. Val(SS,fpc_Val_int64_AnsiStr,Code);
  644. end;
  645. end;
  646. {$endif CPU64}
  647. procedure fpc_AnsiStr_Float(d : ValReal;len,fr,rt : SizeInt;var s : ansistring);[public,alias:'FPC_ANSISTR_FLOAT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  648. var
  649. ss: ShortString;
  650. begin
  651. str_real(len,fr,d,treal_type(rt),ss);
  652. s:=ss;
  653. end;
  654. {$ifdef STR_USES_VALINT}
  655. Procedure fpc_AnsiStr_UInt(v : ValUInt;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_VALUINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  656. {$else}
  657. Procedure fpc_AnsiStr_Longword(v : Longword;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_LONGWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  658. {$endif}
  659. Var
  660. SS : ShortString;
  661. begin
  662. str(v:Len,SS);
  663. S:=SS;
  664. end;
  665. {$ifdef STR_USES_VALINT}
  666. Procedure fpc_AnsiStr_SInt(v : ValSInt;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_VALSINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  667. {$else}
  668. Procedure fpc_AnsiStr_Longint(v : Longint; Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  669. {$endif}
  670. Var
  671. SS : ShortString;
  672. begin
  673. str (v:Len,SS);
  674. S:=SS;
  675. end;
  676. {$ifndef CPU64}
  677. Procedure fpc_AnsiStr_QWord(v : QWord;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_QWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  678. Var
  679. SS : ShortString;
  680. begin
  681. str(v:Len,SS);
  682. S:=SS;
  683. end;
  684. Procedure fpc_AnsiStr_Int64(v : Int64; Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_INT64']; {$ifdef hascompilerproc} compilerproc; {$endif}
  685. Var
  686. SS : ShortString;
  687. begin
  688. str (v:Len,SS);
  689. S:=SS;
  690. end;
  691. {$endif CPU64}
  692. Procedure Delete (Var S : AnsiString; Index,Size: SizeInt);
  693. Var
  694. LS : SizeInt;
  695. begin
  696. ls:=Length(S);
  697. If (Index>LS) or (Index<=0) or (Size<=0) then
  698. exit;
  699. UniqueString (S);
  700. If (Size>LS-Index) then // Size+Index gives overflow ??
  701. Size:=LS-Index+1;
  702. If (Size<=LS-Index) then
  703. begin
  704. Dec(Index);
  705. Move(PByte(Pointer(S))[Index+Size],PByte(Pointer(S))[Index],LS-Index-Size+1);
  706. end;
  707. Setlength(S,LS-Size);
  708. end;
  709. Procedure Insert (Const Source : AnsiString; Var S : AnsiString; Index : SizeInt);
  710. var
  711. Temp : AnsiString;
  712. LS : SizeInt;
  713. begin
  714. If Length(Source)=0 then
  715. exit;
  716. if index <= 0 then
  717. index := 1;
  718. Ls:=Length(S);
  719. if index > LS then
  720. index := LS+1;
  721. Dec(Index);
  722. Pointer(Temp) := NewAnsiString(Length(Source)+LS);
  723. SetLength(Temp,Length(Source)+LS);
  724. If Index>0 then
  725. move (Pointer(S)^,Pointer(Temp)^,Index);
  726. Move (Pointer(Source)^,PByte(Temp)[Index],Length(Source));
  727. If (LS-Index)>0 then
  728. Move(PByte(Pointer(S))[Index],PByte(temp)[Length(Source)+index],LS-Index);
  729. S:=Temp;
  730. end;
  731. Function StringOfChar(c : char;l : SizeInt) : AnsiString;
  732. begin
  733. SetLength(StringOfChar,l);
  734. FillChar(Pointer(StringOfChar)^,Length(StringOfChar),c);
  735. end;
  736. Procedure SetString (Var S : AnsiString; Buf : PChar; Len : SizeInt);
  737. begin
  738. SetLength(S,Len);
  739. If (Buf<>Nil) then
  740. begin
  741. Move (Buf[0],S[1],Len);
  742. end;
  743. end;
  744. function upcase(const s : ansistring) : ansistring;
  745. var
  746. i : SizeInt;
  747. begin
  748. Setlength(result,length(s));
  749. for i := 1 to length (s) do
  750. result[i] := upcase(s[i]);
  751. end;
  752. function lowercase(const s : ansistring) : ansistring;
  753. var
  754. i : SizeInt;
  755. begin
  756. Setlength(result,length(s));
  757. for i := 1 to length (s) do
  758. result[i] := lowercase(s[i]);
  759. end;
  760. {
  761. $Log$
  762. Revision 1.47 2004-07-12 17:58:19 peter
  763. * remove maxlen field from ansistring/widestrings
  764. Revision 1.46 2004/07/02 21:21:09 peter
  765. * decr ref doesn't reset pointer
  766. * finalize resets pointer for astring,wstring
  767. Revision 1.45 2004/05/29 15:39:08 florian
  768. * the decr functions set the data now to nil
  769. Revision 1.44 2004/05/16 16:52:28 peter
  770. * small fix for 1.0.x
  771. Revision 1.43 2004/05/01 23:55:18 peter
  772. * replace strlenint with sizeint
  773. Revision 1.42 2004/04/29 18:59:43 peter
  774. * str() helpers now also use valint/valuint
  775. * int64/qword helpers disabled for cpu64
  776. Revision 1.41 2004/01/21 22:14:05 peter
  777. * 1.0.x fix
  778. Revision 1.40 2004/01/21 22:02:18 peter
  779. * decrref does not reset always to nil, only when string is disposed.
  780. the reset to nil for temps is done by the compiler
  781. Revision 1.39 2003/06/17 19:24:08 jonas
  782. * fixed conversion of fpc_*str_unique to compilerproc
  783. Revision 1.38 2003/06/17 16:38:53 jonas
  784. * fpc_ansistr|widestr_unique is now a function so it can be used as
  785. compilerproc
  786. Revision 1.37 2003/05/01 08:05:23 florian
  787. * started to make the rtl 64 bit save by introducing SizeInt and SizeUInt (similar to size_t of C)
  788. Revision 1.36 2003/02/26 19:16:55 jonas
  789. * fixed setstring (+- like suggested by Dimitry Sibiryakov)
  790. Revision 1.35 2002/12/09 08:33:31 michael
  791. + Fixed range check error and others in Delete
  792. Revision 1.34 2002/12/07 14:34:30 carl
  793. - avoid warnings (add typecast)
  794. Revision 1.33 2002/10/21 19:52:47 jonas
  795. Revision 1.1.2.17 2002/12/09 08:32:34 michael
  796. + Fixed range check error and others in Delete
  797. Revision 1.1.2.16 2002/10/21 19:30:57 jonas
  798. * fixed some buffer overflow errors in SetString (both short and
  799. ansistring versions) (merged)
  800. Revision 1.32 2002/10/20 12:59:21 jonas
  801. * fixed ansistring append helpers so they preserve the terminating #0
  802. * optimized SetLength() so that it uses reallocmem in case the refcount
  803. of the target string is 1
  804. Revision 1.31 2002/10/19 17:06:50 michael
  805. + Added check for nil buffer to setstring
  806. Revision 1.30 2002/10/17 12:43:00 florian
  807. + ansistring_append* implemented
  808. Revision 1.29 2002/10/02 18:21:51 peter
  809. * Copy() changed to internal function calling compilerprocs
  810. * FPC_SHORTSTR_COPY renamed to FPC_SHORTSTR_ASSIGN because of the
  811. new copy functions
  812. Revision 1.28 2002/09/14 11:20:50 carl
  813. * Delphi compatibility fix (with string routines)
  814. Revision 1.27 2002/09/07 21:10:47 carl
  815. * cardinal -> longword
  816. - remove some unused routines
  817. Revision 1.26 2002/09/07 15:07:44 peter
  818. * old logs removed and tabs fixed
  819. Revision 1.25 2002/04/26 15:19:05 peter
  820. * use saveregisters for incr routines, saves also problems with
  821. the optimizer
  822. Revision 1.24 2002/04/25 20:14:56 peter
  823. * updated compilerprocs
  824. * incr ref count has now a value argument instead of var
  825. Revision 1.23 2002/01/07 13:23:53 jonas
  826. * fixed bug in fpc_char_to_ansistr when converting #0 (found by Peter)
  827. }