astrings.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969
  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);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[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);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif} [external name 'FPC_ANSISTR_DECR_REF'];
  97. {$endif hascompilerproc}
  98. {$ifdef hascompilerproc}
  99. Procedure fpc_AnsiStr_Incr_Ref (S : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[Public,Alias:'FPC_ANSISTR_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  100. {$else}
  101. Procedure fpc_AnsiStr_Incr_Ref (Var S : Pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[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);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[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. Var
  220. Size : SizeInt;
  221. begin
  222. Size:=Length(S2);
  223. Setlength (ansistring(s1),Size);
  224. if Size>0 then
  225. Move(S2[1],s1^,Size);
  226. end;
  227. {$endif hascompilerproc}
  228. Function fpc_Char_To_AnsiStr(const c : Char): AnsiString; {$ifdef hascompilerproc} compilerproc; {$endif}
  229. {
  230. Converts a Char to a AnsiString;
  231. }
  232. begin
  233. Setlength (fpc_Char_To_AnsiStr,1);
  234. PByte(Pointer(fpc_Char_To_AnsiStr))^:=byte(c);
  235. { Terminating Zero }
  236. PByte(Pointer(fpc_Char_To_AnsiStr)+1)^:=0;
  237. end;
  238. { old style helper }
  239. {$ifndef hascompilerproc}
  240. Procedure fpc_Char_To_AnsiStr(var S1 : Pointer; c : Char);[Public, alias: 'FPC_CHAR_TO_ANSISTR'];
  241. begin
  242. s1 := pointer(fpc_Char_To_AnsiStr(c));
  243. end;
  244. {$endif hascompilerproc}
  245. Function fpc_PChar_To_AnsiStr(const p : pchar): ansistring; {$ifdef hascompilerproc} compilerproc; {$endif}
  246. Var
  247. L : SizeInt;
  248. begin
  249. if (not assigned(p)) or (p[0]=#0) Then
  250. { result is automatically set to '' }
  251. exit;
  252. l:=IndexChar(p^,-1,#0);
  253. SetLength(fpc_PChar_To_AnsiStr,L);
  254. Move (P[0],Pointer(fpc_PChar_To_AnsiStr)^,L)
  255. end;
  256. { old style helper }
  257. {$ifndef hascompilerproc}
  258. Procedure fpc_PChar_To_AnsiStr(var a : ansistring;p : pchar);[Public,Alias : 'FPC_PCHAR_TO_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  259. begin
  260. pointer(a) := pointer(fpc_PChar_To_AnsiStr(p));
  261. end;
  262. {$endif hascompilerproc}
  263. Function fpc_CharArray_To_AnsiStr(const arr: array of char): ansistring; {$ifdef hascompilerproc} compilerproc; {$endif}
  264. var
  265. i : SizeInt;
  266. begin
  267. if arr[0]=#0 Then
  268. { result is automatically set to '' }
  269. exit;
  270. i:=IndexChar(arr,high(arr)+1,#0);
  271. if i = -1 then
  272. i := high(arr)+1;
  273. SetLength(fpc_CharArray_To_AnsiStr,i);
  274. Move (arr[0],Pointer(fpc_CharArray_To_AnsiStr)^,i);
  275. end;
  276. { old style helper }
  277. {$ifndef hascompilerproc}
  278. { the declaration below is the same as }
  279. { which is what the old helper was (we need the parameter as "array of char" type }
  280. { so we can pass it to the new style helper (JM) }
  281. Procedure fpc_CharArray_To_AnsiStr(var a : ansistring; p: pointer; len: SizeInt);[Public,Alias : 'FPC_CHARARRAY_TO_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  282. var
  283. src: pchar;
  284. i: SizeInt;
  285. begin
  286. src := pchar(p);
  287. if src[0]=#0 Then
  288. { result is automatically set to '' }
  289. begin
  290. pointer(a) := nil;
  291. exit;
  292. end;
  293. i:=IndexChar(src^,len,#0);
  294. if i = -1 then
  295. i := len;
  296. pointer(a) := NewAnsiString(i);
  297. Move (src^,a[1],i);
  298. end;
  299. {$endif not hascompilerproc}
  300. {$ifdef hascompilerproc}
  301. { note: inside the compiler, the resulttype is modified to be the length }
  302. { of the actual chararray to which we convert (JM) }
  303. function fpc_ansistr_to_chararray(arraysize: SizeInt; const src: ansistring): fpc_big_chararray; [public, alias: 'FPC_ANSISTR_TO_CHARARRAY']; compilerproc;
  304. var
  305. len: SizeInt;
  306. begin
  307. len := length(src);
  308. if len > arraysize then
  309. len := arraysize;
  310. { make sure we don't try to access element 1 of the ansistring if it's nil }
  311. if len > 0 then
  312. move(src[1],fpc_ansistr_to_chararray[0],len);
  313. fillchar(fpc_ansistr_to_chararray[len],arraysize-len,0);
  314. end;
  315. {$endif hascompilerproc}
  316. Function fpc_AnsiStr_Compare(const S1,S2 : AnsiString): SizeInt;[Public,Alias : 'FPC_ANSISTR_COMPARE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  317. {
  318. Compares 2 AnsiStrings;
  319. The result is
  320. <0 if S1<S2
  321. 0 if S1=S2
  322. >0 if S1>S2
  323. }
  324. Var
  325. MaxI,Temp : SizeInt;
  326. begin
  327. if pointer(S1)=pointer(S2) then
  328. begin
  329. fpc_AnsiStr_Compare:=0;
  330. exit;
  331. end;
  332. Maxi:=Length(S1);
  333. temp:=Length(S2);
  334. If MaxI>Temp then
  335. MaxI:=Temp;
  336. Temp:=CompareByte(S1[1],S2[1],MaxI);
  337. if temp=0 then
  338. temp:=Length(S1)-Length(S2);
  339. fpc_AnsiStr_Compare:=Temp;
  340. end;
  341. Procedure fpc_AnsiStr_CheckZero(p : pointer);[Public,Alias : 'FPC_ANSISTR_CHECKZERO']; {$ifdef hascompilerproc} compilerproc; {$endif}
  342. begin
  343. if p=nil then
  344. HandleErrorFrame(201,get_frame);
  345. end;
  346. Procedure fpc_AnsiStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_ANSISTR_RANGECHECK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  347. begin
  348. if (index>len) or (Index<1) then
  349. HandleErrorFrame(201,get_frame);
  350. end;
  351. {$ifndef INTERNSETLENGTH}
  352. Procedure SetLength (Var S : AnsiString; l : SizeInt);
  353. {$else INTERNSETLENGTH}
  354. Procedure fpc_AnsiStr_SetLength (Var S : AnsiString; l : SizeInt);[Public,Alias : 'FPC_ANSISTR_SETLENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  355. {$endif INTERNSETLENGTH}
  356. {
  357. Sets The length of string S to L.
  358. Makes sure S is unique, and contains enough room.
  359. }
  360. Var
  361. Temp : Pointer;
  362. movelen : SizeInt;
  363. begin
  364. if (l>0) then
  365. begin
  366. if Pointer(S)=nil then
  367. begin
  368. { Need a complete new string...}
  369. Pointer(s):=NewAnsiString(l);
  370. end
  371. else if (PAnsiRec(Pointer(S)-FirstOff)^.Ref = 1) then
  372. begin
  373. Dec(Pointer(S),FirstOff);
  374. if AnsiRecLen+L>MemSize(Pointer(s)) then
  375. reallocmem(pointer(S),AnsiRecLen+L);
  376. Inc(Pointer(S),FirstOff);
  377. end
  378. else
  379. begin
  380. { Reallocation is needed... }
  381. Temp:=Pointer(NewAnsiString(L));
  382. if Length(S)>0 then
  383. begin
  384. if l < succ(length(s)) then
  385. movelen := l
  386. { also move terminating null }
  387. else movelen := succ(length(s));
  388. Move(Pointer(S)^,Temp^,movelen);
  389. end;
  390. fpc_ansistr_decr_ref(Pointer(S));
  391. Pointer(S):=Temp;
  392. end;
  393. { Force nil termination in case it gets shorter }
  394. PByte(Pointer(S)+l)^:=0;
  395. PAnsiRec(Pointer(S)-FirstOff)^.Len:=l;
  396. end
  397. else
  398. begin
  399. { Length=0 }
  400. if Pointer(S)<>nil then
  401. fpc_ansistr_decr_ref (Pointer(S));
  402. Pointer(S):=Nil;
  403. end;
  404. end;
  405. {$ifdef EXTRAANSISHORT}
  406. Function fpc_AnsiStr_ShortStr_Compare (Var S1 : Pointer; Var S2 : ShortString): SizeInt; {$ifdef hascompilerproc} compilerproc; {$endif}
  407. {
  408. Compares a AnsiString with a ShortString;
  409. The result is
  410. <0 if S1<S2
  411. 0 if S1=S2
  412. >0 if S1>S2
  413. }
  414. Var
  415. i,MaxI,Temp : SizeInt;
  416. begin
  417. Temp:=0;
  418. i:=0;
  419. MaxI:=Length(AnsiString(S1));
  420. if MaxI>byte(S2[0]) then
  421. MaxI:=Byte(S2[0]);
  422. While (i<MaxI) and (Temp=0) do
  423. begin
  424. Temp:= PByte(S1+I)^ - Byte(S2[i+1]);
  425. inc(i);
  426. end;
  427. AnsiStr_ShortStr_Compare:=Temp;
  428. end;
  429. {$endif EXTRAANSISHORT}
  430. {*****************************************************************************
  431. Public functions, In interface.
  432. *****************************************************************************}
  433. {$ifndef INTERNLENGTH}
  434. Function Length (Const S : AnsiString) : SizeInt;
  435. {
  436. Returns the length of an AnsiString.
  437. Takes in acount that zero strings are NIL;
  438. }
  439. begin
  440. If Pointer(S)=Nil then
  441. Length:=0
  442. else
  443. Length:=PAnsiRec(Pointer(S)-FirstOff)^.Len;
  444. end;
  445. {$endif INTERNLENGTH}
  446. {$ifdef HASCOMPILERPROC}
  447. { overloaded version of UniqueString for interface }
  448. Procedure UniqueString(Var S : AnsiString); [external name 'FPC_ANSISTR_UNIQUE'];
  449. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  450. {$else}
  451. Procedure UniqueString(Var S : AnsiString); [Public,Alias : 'FPC_ANSISTR_UNIQUE'];
  452. {$endif}
  453. {
  454. Make sure reference count of S is 1,
  455. using copy-on-write semantics.
  456. }
  457. Var
  458. SNew : Pointer;
  459. L : SizeInt;
  460. begin
  461. {$ifdef HASCOMPILERPROC}
  462. pointer(result) := pointer(s);
  463. {$endif}
  464. If Pointer(S)=Nil then
  465. exit;
  466. if PAnsiRec(Pointer(S)-Firstoff)^.Ref<>1 then
  467. begin
  468. L:=PAnsiRec(Pointer(S)-FirstOff)^.len;
  469. SNew:=NewAnsiString (L);
  470. Move (Pointer(S)^,SNew^,L+1);
  471. PAnsiRec(SNew-FirstOff)^.len:=L;
  472. fpc_ansistr_decr_ref (Pointer(S)); { Thread safe }
  473. pointer(S):=SNew;
  474. {$ifdef HASCOMPILERPROC}
  475. pointer(result):=SNew;
  476. {$endif}
  477. end;
  478. end;
  479. Procedure fpc_ansistr_append_char(Var S : AnsiString;c : char); [Public,Alias : 'FPC_ANSISTR_APPEND_CHAR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  480. begin
  481. SetLength(S,length(S)+1);
  482. S[length(S)]:=c;
  483. PByte(Pointer(S)+length(S))^:=0; { Terminating Zero }
  484. end;
  485. Procedure fpc_ansistr_append_shortstring(Var S : AnsiString;Str : ShortString); [Public,Alias : 'FPC_ANSISTR_APPEND_SHORTSTRING']; {$ifdef hascompilerproc} compilerproc; {$endif}
  486. var
  487. ofs : SizeInt;
  488. begin
  489. ofs:=Length(S);
  490. SetLength(S,ofs+length(Str));
  491. move(Str[1],S[ofs+1],length(Str));
  492. PByte(Pointer(S)+length(S))^:=0; { Terminating Zero }
  493. end;
  494. Procedure fpc_ansistr_append_ansistring(Var S : AnsiString;Str : AnsiString); [Public,Alias : 'FPC_ANSISTR_APPEND_ANSISTRING']; {$ifdef hascompilerproc} compilerproc; {$endif}
  495. var
  496. ofs : SizeInt;
  497. begin
  498. if Str<>'' then
  499. begin
  500. ofs:=Length(S);
  501. SetLength(S,ofs+length(Str));
  502. move(Str[1],S[ofs+1],length(Str)+1);
  503. end;
  504. end;
  505. {$ifdef interncopy}
  506. Function Fpc_Ansistr_Copy (Const S : AnsiString; Index,Size : SizeInt) : AnsiString;compilerproc;
  507. {$else}
  508. Function Copy (Const S : AnsiString; Index,Size : SizeInt) : AnsiString;
  509. {$endif}
  510. var
  511. ResultAddress : Pointer;
  512. begin
  513. ResultAddress:=Nil;
  514. dec(index);
  515. if Index < 0 then
  516. Index := 0;
  517. { Check Size. Accounts for Zero-length S, the double check is needed because
  518. Size can be maxint and will get <0 when adding index }
  519. if (Size>Length(S)) or
  520. (Index+Size>Length(S)) then
  521. Size:=Length(S)-Index;
  522. If Size>0 then
  523. begin
  524. If Index<0 Then
  525. Index:=0;
  526. ResultAddress:=Pointer(NewAnsiString (Size));
  527. if ResultAddress<>Nil then
  528. begin
  529. Move (Pointer(Pointer(S)+index)^,ResultAddress^,Size);
  530. PAnsiRec(ResultAddress-FirstOff)^.Len:=Size;
  531. PByte(ResultAddress+Size)^:=0;
  532. end;
  533. end;
  534. {$ifdef interncopy}
  535. Pointer(fpc_ansistr_Copy):=ResultAddress;
  536. {$else}
  537. Pointer(Copy):=ResultAddress;
  538. {$endif}
  539. end;
  540. Function Pos (Const Substr : AnsiString; Const Source : AnsiString) : SizeInt;
  541. var
  542. i,MaxLen : SizeInt;
  543. pc : pchar;
  544. begin
  545. Pos:=0;
  546. if Length(SubStr)>0 then
  547. begin
  548. MaxLen:=Length(source)-Length(SubStr);
  549. i:=0;
  550. pc:=@source[1];
  551. while (i<=MaxLen) do
  552. begin
  553. inc(i);
  554. if (SubStr[1]=pc^) and
  555. (CompareChar(Substr[1],pc^,Length(SubStr))=0) then
  556. begin
  557. Pos:=i;
  558. exit;
  559. end;
  560. inc(pc);
  561. end;
  562. end;
  563. end;
  564. { Faster version for a char alone. Must be implemented because }
  565. { pos(c: char; const s: shortstring) also exists, so otherwise }
  566. { using pos(char,pchar) will always call the shortstring version }
  567. { (exact match for first argument), also with $h+ (JM) }
  568. Function Pos (c : Char; Const s : AnsiString) : SizeInt;
  569. var
  570. i: SizeInt;
  571. pc : pchar;
  572. begin
  573. pc:=@s[1];
  574. for i:=1 to length(s) do
  575. begin
  576. if pc^=c then
  577. begin
  578. pos:=i;
  579. exit;
  580. end;
  581. inc(pc);
  582. end;
  583. pos:=0;
  584. end;
  585. Function fpc_Val_Real_AnsiStr(Const S : AnsiString; Var Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  586. Var
  587. SS : String;
  588. begin
  589. fpc_Val_Real_AnsiStr := 0;
  590. if length(S) > 255 then
  591. code := 256
  592. else
  593. begin
  594. SS := S;
  595. Val(SS,fpc_Val_Real_AnsiStr,code);
  596. end;
  597. end;
  598. Function fpc_Val_UInt_AnsiStr (Const S : AnsiString; Var Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  599. Var
  600. SS : ShortString;
  601. begin
  602. fpc_Val_UInt_AnsiStr := 0;
  603. if length(S) > 255 then
  604. code := 256
  605. else
  606. begin
  607. SS := S;
  608. Val(SS,fpc_Val_UInt_AnsiStr,code);
  609. end;
  610. end;
  611. Function fpc_Val_SInt_AnsiStr (DestSize: SizeInt; Const S : AnsiString; Var Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  612. Var
  613. SS : ShortString;
  614. begin
  615. fpc_Val_SInt_AnsiStr:=0;
  616. if length(S)>255 then
  617. code:=256
  618. else
  619. begin
  620. SS := S;
  621. fpc_Val_SInt_AnsiStr := fpc_Val_SInt_ShortStr(DestSize,SS,Code);
  622. end;
  623. end;
  624. {$ifndef CPU64}
  625. Function fpc_Val_qword_AnsiStr (Const S : AnsiString; Var Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  626. Var
  627. SS : ShortString;
  628. begin
  629. fpc_Val_qword_AnsiStr:=0;
  630. if length(S)>255 then
  631. code:=256
  632. else
  633. begin
  634. SS := S;
  635. Val(SS,fpc_Val_qword_AnsiStr,Code);
  636. end;
  637. end;
  638. Function fpc_Val_int64_AnsiStr (Const S : AnsiString; Var Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  639. Var
  640. SS : ShortString;
  641. begin
  642. fpc_Val_int64_AnsiStr:=0;
  643. if length(S)>255 then
  644. code:=256
  645. else
  646. begin
  647. SS := s;
  648. Val(SS,fpc_Val_int64_AnsiStr,Code);
  649. end;
  650. end;
  651. {$endif CPU64}
  652. procedure fpc_AnsiStr_Float(d : ValReal;len,fr,rt : SizeInt;var s : ansistring);[public,alias:'FPC_ANSISTR_FLOAT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  653. var
  654. ss: ShortString;
  655. begin
  656. str_real(len,fr,d,treal_type(rt),ss);
  657. s:=ss;
  658. end;
  659. {$ifdef STR_USES_VALINT}
  660. Procedure fpc_AnsiStr_UInt(v : ValUInt;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_VALUINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  661. {$else}
  662. Procedure fpc_AnsiStr_Longword(v : Longword;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_LONGWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  663. {$endif}
  664. Var
  665. SS : ShortString;
  666. begin
  667. str(v:Len,SS);
  668. S:=SS;
  669. end;
  670. {$ifdef STR_USES_VALINT}
  671. Procedure fpc_AnsiStr_SInt(v : ValSInt;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_VALSINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  672. {$else}
  673. Procedure fpc_AnsiStr_Longint(v : Longint; Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  674. {$endif}
  675. Var
  676. SS : ShortString;
  677. begin
  678. str (v:Len,SS);
  679. S:=SS;
  680. end;
  681. {$ifndef CPU64}
  682. Procedure fpc_AnsiStr_QWord(v : QWord;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_QWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  683. Var
  684. SS : ShortString;
  685. begin
  686. str(v:Len,SS);
  687. S:=SS;
  688. end;
  689. Procedure fpc_AnsiStr_Int64(v : Int64; Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_INT64']; {$ifdef hascompilerproc} compilerproc; {$endif}
  690. Var
  691. SS : ShortString;
  692. begin
  693. str (v:Len,SS);
  694. S:=SS;
  695. end;
  696. {$endif CPU64}
  697. Procedure Delete (Var S : AnsiString; Index,Size: SizeInt);
  698. Var
  699. LS : SizeInt;
  700. begin
  701. ls:=Length(S);
  702. If (Index>LS) or (Index<=0) or (Size<=0) then
  703. exit;
  704. UniqueString (S);
  705. If (Size>LS-Index) then // Size+Index gives overflow ??
  706. Size:=LS-Index+1;
  707. If (Size<=LS-Index) then
  708. begin
  709. Dec(Index);
  710. Move(PByte(Pointer(S))[Index+Size],PByte(Pointer(S))[Index],LS-Index-Size+1);
  711. end;
  712. Setlength(S,LS-Size);
  713. end;
  714. Procedure Insert (Const Source : AnsiString; Var S : AnsiString; Index : SizeInt);
  715. var
  716. Temp : AnsiString;
  717. LS : SizeInt;
  718. begin
  719. If Length(Source)=0 then
  720. exit;
  721. if index <= 0 then
  722. index := 1;
  723. Ls:=Length(S);
  724. if index > LS then
  725. index := LS+1;
  726. Dec(Index);
  727. Pointer(Temp) := NewAnsiString(Length(Source)+LS);
  728. SetLength(Temp,Length(Source)+LS);
  729. If Index>0 then
  730. move (Pointer(S)^,Pointer(Temp)^,Index);
  731. Move (Pointer(Source)^,PByte(Temp)[Index],Length(Source));
  732. If (LS-Index)>0 then
  733. Move(PByte(Pointer(S))[Index],PByte(temp)[Length(Source)+index],LS-Index);
  734. S:=Temp;
  735. end;
  736. Function StringOfChar(c : char;l : SizeInt) : AnsiString;
  737. begin
  738. SetLength(StringOfChar,l);
  739. FillChar(Pointer(StringOfChar)^,Length(StringOfChar),c);
  740. end;
  741. Procedure SetString (Var S : AnsiString; Buf : PChar; Len : SizeInt);
  742. begin
  743. SetLength(S,Len);
  744. If (Buf<>Nil) then
  745. begin
  746. Move (Buf[0],S[1],Len);
  747. end;
  748. end;
  749. function upcase(const s : ansistring) : ansistring;
  750. var
  751. i : SizeInt;
  752. begin
  753. Setlength(result,length(s));
  754. for i := 1 to length (s) do
  755. result[i] := upcase(s[i]);
  756. end;
  757. function lowercase(const s : ansistring) : ansistring;
  758. var
  759. i : SizeInt;
  760. begin
  761. Setlength(result,length(s));
  762. for i := 1 to length (s) do
  763. result[i] := lowercase(s[i]);
  764. end;
  765. {
  766. $Log$
  767. Revision 1.49 2004-10-31 16:21:30 peter
  768. * fix shortstr_to_ansistring for 1.0.x
  769. Revision 1.48 2004/10/24 20:01:41 peter
  770. * saveregisters calling convention is obsolete
  771. Revision 1.47 2004/07/12 17:58:19 peter
  772. * remove maxlen field from ansistring/widestrings
  773. Revision 1.46 2004/07/02 21:21:09 peter
  774. * decr ref doesn't reset pointer
  775. * finalize resets pointer for astring,wstring
  776. Revision 1.45 2004/05/29 15:39:08 florian
  777. * the decr functions set the data now to nil
  778. Revision 1.44 2004/05/16 16:52:28 peter
  779. * small fix for 1.0.x
  780. Revision 1.43 2004/05/01 23:55:18 peter
  781. * replace strlenint with sizeint
  782. Revision 1.42 2004/04/29 18:59:43 peter
  783. * str() helpers now also use valint/valuint
  784. * int64/qword helpers disabled for cpu64
  785. Revision 1.41 2004/01/21 22:14:05 peter
  786. * 1.0.x fix
  787. Revision 1.40 2004/01/21 22:02:18 peter
  788. * decrref does not reset always to nil, only when string is disposed.
  789. the reset to nil for temps is done by the compiler
  790. Revision 1.39 2003/06/17 19:24:08 jonas
  791. * fixed conversion of fpc_*str_unique to compilerproc
  792. Revision 1.38 2003/06/17 16:38:53 jonas
  793. * fpc_ansistr|widestr_unique is now a function so it can be used as
  794. compilerproc
  795. Revision 1.37 2003/05/01 08:05:23 florian
  796. * started to make the rtl 64 bit save by introducing SizeInt and SizeUInt (similar to size_t of C)
  797. Revision 1.36 2003/02/26 19:16:55 jonas
  798. * fixed setstring (+- like suggested by Dimitry Sibiryakov)
  799. Revision 1.35 2002/12/09 08:33:31 michael
  800. + Fixed range check error and others in Delete
  801. Revision 1.34 2002/12/07 14:34:30 carl
  802. - avoid warnings (add typecast)
  803. Revision 1.33 2002/10/21 19:52:47 jonas
  804. Revision 1.1.2.17 2002/12/09 08:32:34 michael
  805. + Fixed range check error and others in Delete
  806. Revision 1.1.2.16 2002/10/21 19:30:57 jonas
  807. * fixed some buffer overflow errors in SetString (both short and
  808. ansistring versions) (merged)
  809. Revision 1.32 2002/10/20 12:59:21 jonas
  810. * fixed ansistring append helpers so they preserve the terminating #0
  811. * optimized SetLength() so that it uses reallocmem in case the refcount
  812. of the target string is 1
  813. Revision 1.31 2002/10/19 17:06:50 michael
  814. + Added check for nil buffer to setstring
  815. Revision 1.30 2002/10/17 12:43:00 florian
  816. + ansistring_append* implemented
  817. Revision 1.29 2002/10/02 18:21:51 peter
  818. * Copy() changed to internal function calling compilerprocs
  819. * FPC_SHORTSTR_COPY renamed to FPC_SHORTSTR_ASSIGN because of the
  820. new copy functions
  821. Revision 1.28 2002/09/14 11:20:50 carl
  822. * Delphi compatibility fix (with string routines)
  823. Revision 1.27 2002/09/07 21:10:47 carl
  824. * cardinal -> longword
  825. - remove some unused routines
  826. Revision 1.26 2002/09/07 15:07:44 peter
  827. * old logs removed and tabs fixed
  828. Revision 1.25 2002/04/26 15:19:05 peter
  829. * use saveregisters for incr routines, saves also problems with
  830. the optimizer
  831. Revision 1.24 2002/04/25 20:14:56 peter
  832. * updated compilerprocs
  833. * incr ref count has now a value argument instead of var
  834. Revision 1.23 2002/01/07 13:23:53 jonas
  835. * fixed bug in fpc_char_to_ansistr when converting #0 (found by Peter)
  836. }