astrings.inc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  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.55 2005-02-14 17:13:22 peter
  778. * truncate log
  779. Revision 1.54 2005/01/28 19:50:51 peter
  780. 1.0.x fixes
  781. Revision 1.53 2005/01/25 18:50:45 peter
  782. * 1.0.x fix
  783. Revision 1.52 2005/01/09 10:38:59 florian
  784. * replaced CompareChar by CompareByte, saves one redirection
  785. }