astrings.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  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. Function fpc_ansistr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_ANSISTR_UNIQUE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  448. {$else}
  449. Procedure fpc_ansistr_Unique(Var S : AnsiString); [Public,Alias : 'FPC_ANSISTR_UNIQUE'];
  450. {$endif}
  451. {
  452. Make sure reference count of S is 1,
  453. using copy-on-write semantics.
  454. }
  455. Var
  456. SNew : Pointer;
  457. L : SizeInt;
  458. begin
  459. {$ifdef HASCOMPILERPROC}
  460. pointer(result) := pointer(s);
  461. {$endif}
  462. If Pointer(S)=Nil then
  463. exit;
  464. if PAnsiRec(Pointer(S)-Firstoff)^.Ref<>1 then
  465. begin
  466. L:=PAnsiRec(Pointer(S)-FirstOff)^.len;
  467. SNew:=NewAnsiString (L);
  468. Move (Pointer(S)^,SNew^,L+1);
  469. PAnsiRec(SNew-FirstOff)^.len:=L;
  470. fpc_ansistr_decr_ref (Pointer(S)); { Thread safe }
  471. pointer(S):=SNew;
  472. {$ifdef HASCOMPILERPROC}
  473. pointer(result):=SNew;
  474. {$endif}
  475. end;
  476. end;
  477. Procedure fpc_ansistr_append_char(Var S : AnsiString;c : char); [Public,Alias : 'FPC_ANSISTR_APPEND_CHAR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  478. begin
  479. SetLength(S,length(S)+1);
  480. S[length(S)]:=c;
  481. PByte(Pointer(S)+length(S))^:=0; { Terminating Zero }
  482. end;
  483. Procedure fpc_ansistr_append_shortstring(Var S : AnsiString;Str : ShortString); [Public,Alias : 'FPC_ANSISTR_APPEND_SHORTSTRING']; {$ifdef hascompilerproc} compilerproc; {$endif}
  484. var
  485. ofs : SizeInt;
  486. begin
  487. if Str='' then
  488. exit;
  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. exit;
  500. ofs:=Length(S);
  501. SetLength(S,ofs+length(Str));
  502. move(Str[1],S[ofs+1],length(Str)+1);
  503. end;
  504. {$ifdef interncopy}
  505. Function Fpc_Ansistr_Copy (Const S : AnsiString; Index,Size : SizeInt) : AnsiString;compilerproc;
  506. {$else}
  507. Function Copy (Const S : AnsiString; Index,Size : SizeInt) : AnsiString;
  508. {$endif}
  509. var
  510. ResultAddress : Pointer;
  511. begin
  512. ResultAddress:=Nil;
  513. dec(index);
  514. if Index < 0 then
  515. Index := 0;
  516. { Check Size. Accounts for Zero-length S, the double check is needed because
  517. Size can be maxint and will get <0 when adding index }
  518. if (Size>Length(S)) or
  519. (Index+Size>Length(S)) then
  520. Size:=Length(S)-Index;
  521. If Size>0 then
  522. begin
  523. If Index<0 Then
  524. Index:=0;
  525. ResultAddress:=Pointer(NewAnsiString (Size));
  526. if ResultAddress<>Nil then
  527. begin
  528. Move (Pointer(Pointer(S)+index)^,ResultAddress^,Size);
  529. PAnsiRec(ResultAddress-FirstOff)^.Len:=Size;
  530. PByte(ResultAddress+Size)^:=0;
  531. end;
  532. end;
  533. {$ifdef interncopy}
  534. Pointer(fpc_ansistr_Copy):=ResultAddress;
  535. {$else}
  536. Pointer(Copy):=ResultAddress;
  537. {$endif}
  538. end;
  539. Function Pos (Const Substr : AnsiString; Const Source : AnsiString) : SizeInt;
  540. var
  541. i,MaxLen : SizeInt;
  542. pc : pchar;
  543. begin
  544. Pos:=0;
  545. if Length(SubStr)>0 then
  546. begin
  547. MaxLen:=Length(source)-Length(SubStr);
  548. i:=0;
  549. pc:=@source[1];
  550. while (i<=MaxLen) do
  551. begin
  552. inc(i);
  553. if (SubStr[1]=pc^) and
  554. (CompareByte(Substr[1],pc^,Length(SubStr))=0) then
  555. begin
  556. Pos:=i;
  557. exit;
  558. end;
  559. inc(pc);
  560. end;
  561. end;
  562. end;
  563. { Faster version for a char alone. Must be implemented because }
  564. { pos(c: char; const s: shortstring) also exists, so otherwise }
  565. { using pos(char,pchar) will always call the shortstring version }
  566. { (exact match for first argument), also with $h+ (JM) }
  567. Function Pos (c : Char; Const s : AnsiString) : SizeInt;
  568. var
  569. i: SizeInt;
  570. pc : pchar;
  571. begin
  572. pc:=@s[1];
  573. for i:=1 to length(s) do
  574. begin
  575. if pc^=c then
  576. begin
  577. pos:=i;
  578. exit;
  579. end;
  580. inc(pc);
  581. end;
  582. pos:=0;
  583. end;
  584. Function fpc_Val_Real_AnsiStr(Const S : AnsiString; Var Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  585. Var
  586. SS : String;
  587. begin
  588. fpc_Val_Real_AnsiStr := 0;
  589. if length(S) > 255 then
  590. code := 256
  591. else
  592. begin
  593. SS := S;
  594. Val(SS,fpc_Val_Real_AnsiStr,code);
  595. end;
  596. end;
  597. Function fpc_Val_UInt_AnsiStr (Const S : AnsiString; Var Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  598. Var
  599. SS : ShortString;
  600. begin
  601. fpc_Val_UInt_AnsiStr := 0;
  602. if length(S) > 255 then
  603. code := 256
  604. else
  605. begin
  606. SS := S;
  607. Val(SS,fpc_Val_UInt_AnsiStr,code);
  608. end;
  609. end;
  610. Function fpc_Val_SInt_AnsiStr (DestSize: SizeInt; Const S : AnsiString; Var Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  611. Var
  612. SS : ShortString;
  613. begin
  614. fpc_Val_SInt_AnsiStr:=0;
  615. if length(S)>255 then
  616. code:=256
  617. else
  618. begin
  619. SS := S;
  620. fpc_Val_SInt_AnsiStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  621. end;
  622. end;
  623. {$ifndef CPU64}
  624. Function fpc_Val_qword_AnsiStr (Const S : AnsiString; Var Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  625. Var
  626. SS : ShortString;
  627. begin
  628. fpc_Val_qword_AnsiStr:=0;
  629. if length(S)>255 then
  630. code:=256
  631. else
  632. begin
  633. SS := S;
  634. Val(SS,fpc_Val_qword_AnsiStr,Code);
  635. end;
  636. end;
  637. Function fpc_Val_int64_AnsiStr (Const S : AnsiString; Var Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_ANSISTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  638. Var
  639. SS : ShortString;
  640. begin
  641. fpc_Val_int64_AnsiStr:=0;
  642. if length(S)>255 then
  643. code:=256
  644. else
  645. begin
  646. SS := s;
  647. Val(SS,fpc_Val_int64_AnsiStr,Code);
  648. end;
  649. end;
  650. {$endif CPU64}
  651. procedure fpc_AnsiStr_Float(d : ValReal;len,fr,rt : SizeInt;var s : ansistring);[public,alias:'FPC_ANSISTR_FLOAT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  652. var
  653. ss: ShortString;
  654. begin
  655. str_real(len,fr,d,treal_type(rt),ss);
  656. s:=ss;
  657. end;
  658. {$ifdef STR_USES_VALINT}
  659. Procedure fpc_AnsiStr_UInt(v : ValUInt;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_VALUINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  660. {$else}
  661. Procedure fpc_AnsiStr_Longword(v : Longword;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_LONGWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  662. {$endif}
  663. Var
  664. SS : ShortString;
  665. begin
  666. str(v:Len,SS);
  667. S:=SS;
  668. end;
  669. {$ifdef STR_USES_VALINT}
  670. Procedure fpc_AnsiStr_SInt(v : ValSInt;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_VALSINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  671. {$else}
  672. Procedure fpc_AnsiStr_Longint(v : Longint; Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  673. {$endif}
  674. Var
  675. SS : ShortString;
  676. begin
  677. str (v:Len,SS);
  678. S:=SS;
  679. end;
  680. {$ifndef CPU64}
  681. Procedure fpc_AnsiStr_QWord(v : QWord;Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_QWORD']; {$ifdef hascompilerproc} compilerproc; {$endif}
  682. Var
  683. SS : ShortString;
  684. begin
  685. str(v:Len,SS);
  686. S:=SS;
  687. end;
  688. Procedure fpc_AnsiStr_Int64(v : Int64; Len : SizeInt; Var S : AnsiString);[Public,Alias : 'FPC_ANSISTR_INT64']; {$ifdef hascompilerproc} compilerproc; {$endif}
  689. Var
  690. SS : ShortString;
  691. begin
  692. str (v:Len,SS);
  693. S:=SS;
  694. end;
  695. {$endif CPU64}
  696. Procedure Delete (Var S : AnsiString; Index,Size: SizeInt);
  697. Var
  698. LS : SizeInt;
  699. begin
  700. ls:=Length(S);
  701. If (Index>LS) or (Index<=0) or (Size<=0) then
  702. exit;
  703. UniqueString (S);
  704. If (Size>LS-Index) then // Size+Index gives overflow ??
  705. Size:=LS-Index+1;
  706. If (Size<=LS-Index) then
  707. begin
  708. Dec(Index);
  709. Move(PByte(Pointer(S))[Index+Size],PByte(Pointer(S))[Index],LS-Index-Size+1);
  710. end;
  711. Setlength(S,LS-Size);
  712. end;
  713. Procedure Insert (Const Source : AnsiString; Var S : AnsiString; Index : SizeInt);
  714. var
  715. Temp : AnsiString;
  716. LS : SizeInt;
  717. begin
  718. If Length(Source)=0 then
  719. exit;
  720. if index <= 0 then
  721. index := 1;
  722. Ls:=Length(S);
  723. if index > LS then
  724. index := LS+1;
  725. Dec(Index);
  726. Pointer(Temp) := NewAnsiString(Length(Source)+LS);
  727. SetLength(Temp,Length(Source)+LS);
  728. If Index>0 then
  729. move (Pointer(S)^,Pointer(Temp)^,Index);
  730. Move (Pointer(Source)^,PByte(Temp)[Index],Length(Source));
  731. If (LS-Index)>0 then
  732. Move(PByte(Pointer(S))[Index],PByte(temp)[Length(Source)+index],LS-Index);
  733. S:=Temp;
  734. end;
  735. Function StringOfChar(c : char;l : SizeInt) : AnsiString;
  736. begin
  737. SetLength(StringOfChar,l);
  738. FillChar(Pointer(StringOfChar)^,Length(StringOfChar),c);
  739. end;
  740. Procedure SetString (Var S : AnsiString; Buf : PChar; Len : SizeInt);
  741. begin
  742. SetLength(S,Len);
  743. If (Buf<>Nil) then
  744. begin
  745. Move (Buf[0],S[1],Len);
  746. end;
  747. end;
  748. function upcase(const s : ansistring) : ansistring;
  749. var
  750. i : SizeInt;
  751. begin
  752. Setlength(result,length(s));
  753. for i := 1 to length (s) do
  754. result[i] := upcase(s[i]);
  755. end;
  756. function lowercase(const s : ansistring) : ansistring;
  757. var
  758. i : SizeInt;
  759. begin
  760. Setlength(result,length(s));
  761. for i := 1 to length (s) do
  762. result[i] := lowercase(s[i]);
  763. end;
  764. {
  765. $Log$
  766. Revision 1.52 2005-01-09 10:38:59 florian
  767. * replaced CompareChar by CompareByte, saves one redirection
  768. Revision 1.51 2004/12/02 17:56:01 peter
  769. * prevent crash when appending empty string
  770. Revision 1.50 2004/11/17 22:19:04 peter
  771. internconst, internproc and some external declarations moved to interface
  772. Revision 1.49 2004/10/31 16:21:30 peter
  773. * fix shortstr_to_ansistring for 1.0.x
  774. Revision 1.48 2004/10/24 20:01:41 peter
  775. * saveregisters calling convention is obsolete
  776. Revision 1.47 2004/07/12 17:58:19 peter
  777. * remove maxlen field from ansistring/widestrings
  778. Revision 1.46 2004/07/02 21:21:09 peter
  779. * decr ref doesn't reset pointer
  780. * finalize resets pointer for astring,wstring
  781. Revision 1.45 2004/05/29 15:39:08 florian
  782. * the decr functions set the data now to nil
  783. Revision 1.44 2004/05/16 16:52:28 peter
  784. * small fix for 1.0.x
  785. Revision 1.43 2004/05/01 23:55:18 peter
  786. * replace strlenint with sizeint
  787. Revision 1.42 2004/04/29 18:59:43 peter
  788. * str() helpers now also use valint/valuint
  789. * int64/qword helpers disabled for cpu64
  790. Revision 1.41 2004/01/21 22:14:05 peter
  791. * 1.0.x fix
  792. Revision 1.40 2004/01/21 22:02:18 peter
  793. * decrref does not reset always to nil, only when string is disposed.
  794. the reset to nil for temps is done by the compiler
  795. Revision 1.39 2003/06/17 19:24:08 jonas
  796. * fixed conversion of fpc_*str_unique to compilerproc
  797. Revision 1.38 2003/06/17 16:38:53 jonas
  798. * fpc_ansistr|widestr_unique is now a function so it can be used as
  799. compilerproc
  800. Revision 1.37 2003/05/01 08:05:23 florian
  801. * started to make the rtl 64 bit save by introducing SizeInt and SizeUInt (similar to size_t of C)
  802. Revision 1.36 2003/02/26 19:16:55 jonas
  803. * fixed setstring (+- like suggested by Dimitry Sibiryakov)
  804. Revision 1.35 2002/12/09 08:33:31 michael
  805. + Fixed range check error and others in Delete
  806. Revision 1.34 2002/12/07 14:34:30 carl
  807. - avoid warnings (add typecast)
  808. Revision 1.33 2002/10/21 19:52:47 jonas
  809. Revision 1.1.2.17 2002/12/09 08:32:34 michael
  810. + Fixed range check error and others in Delete
  811. Revision 1.1.2.16 2002/10/21 19:30:57 jonas
  812. * fixed some buffer overflow errors in SetString (both short and
  813. ansistring versions) (merged)
  814. Revision 1.32 2002/10/20 12:59:21 jonas
  815. * fixed ansistring append helpers so they preserve the terminating #0
  816. * optimized SetLength() so that it uses reallocmem in case the refcount
  817. of the target string is 1
  818. Revision 1.31 2002/10/19 17:06:50 michael
  819. + Added check for nil buffer to setstring
  820. Revision 1.30 2002/10/17 12:43:00 florian
  821. + ansistring_append* implemented
  822. Revision 1.29 2002/10/02 18:21:51 peter
  823. * Copy() changed to internal function calling compilerprocs
  824. * FPC_SHORTSTR_COPY renamed to FPC_SHORTSTR_ASSIGN because of the
  825. new copy functions
  826. Revision 1.28 2002/09/14 11:20:50 carl
  827. * Delphi compatibility fix (with string routines)
  828. Revision 1.27 2002/09/07 21:10:47 carl
  829. * cardinal -> longword
  830. - remove some unused routines
  831. Revision 1.26 2002/09/07 15:07:44 peter
  832. * old logs removed and tabs fixed
  833. Revision 1.25 2002/04/26 15:19:05 peter
  834. * use saveregisters for incr routines, saves also problems with
  835. the optimizer
  836. Revision 1.24 2002/04/25 20:14:56 peter
  837. * updated compilerprocs
  838. * incr ref count has now a value argument instead of var
  839. Revision 1.23 2002/01/07 13:23:53 jonas
  840. * fixed bug in fpc_char_to_ansistr when converting #0 (found by Peter)
  841. }