astrings.inc 27 KB

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