astrings.inc 24 KB

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