syssb.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. { TStringBuilder }
  2. constructor TStringBuilder.Create;
  3. begin
  4. Create(DefaultCapacity,Maxint);
  5. end;
  6. constructor TStringBuilder.Create(const AValue: SBString; aCapacity: Integer);
  7. begin
  8. Create(aCapacity,Maxint);
  9. if (system.Length(AValue)>0) then
  10. Append(AValue);
  11. end;
  12. constructor TStringBuilder.Create(const AValue: SBString; StartIndex, Alength,
  13. aCapacity: Integer);
  14. begin
  15. Create(Copy(AValue,StartIndex+1,Alength), aCapacity);
  16. end;
  17. constructor TStringBuilder.Create(aCapacity, aMaxCapacity: Integer);
  18. begin
  19. FMaxCapacity:=aMaxCapacity;
  20. Capacity:=aCapacity;
  21. FLength:=0;
  22. end;
  23. constructor TStringBuilder.Create(aCapacity: Integer);
  24. begin
  25. Create(aCapacity,MaxInt);
  26. end;
  27. constructor TStringBuilder.Create(const AValue: SBString);
  28. begin
  29. Create(aValue,DefaultCapacity);
  30. end;
  31. { Property getter/setter }
  32. function TStringBuilder.GetLength: Integer;
  33. begin
  34. Result:=FLength;
  35. end;
  36. function TStringBuilder.GetCapacity: Integer;
  37. begin
  38. Result:=System.Length(FData);
  39. end;
  40. function TStringBuilder.GetC(Index: Integer): SBChar;
  41. begin
  42. CheckNegative(Index,'Index');
  43. CheckRange(Index,0,Length);
  44. Result:=FData[Index];
  45. end;
  46. procedure TStringBuilder.SetC(Index: Integer; AValue: SBChar);
  47. begin
  48. CheckNegative(Index,'Index');
  49. CheckRange(Index,0,Length-1);
  50. FData[Index]:=AValue;
  51. end;
  52. procedure TStringBuilder.SetLength(AValue: Integer);
  53. begin
  54. CheckNegative(AValue,'AValue');
  55. CheckRange(AValue,0,MaxCapacity);
  56. if AValue>Capacity then
  57. Grow;
  58. Flength:=AValue;
  59. end;
  60. { Check functions }
  61. procedure TStringBuilder.CheckRange(Idx, Count, MaxLen: Integer);
  62. begin
  63. if (Idx<0) or (Idx+Count>MaxLen) then
  64. Raise ERangeError.CreateFmt(SListIndexError,[Idx]);
  65. end;
  66. procedure TStringBuilder.CheckNegative(const AValue: Integer;
  67. const AName: SBString);
  68. begin
  69. if (AValue<0) then
  70. Raise ERangeError.CreateFmt(SParamIsNegative,[AName])
  71. end;
  72. { These do the actual Appending/Inserting }
  73. procedure TStringBuilder.DoAppend(const S: {$IFDEF SBUNICODE}SBString{$ELSE}RawByteString{$ENDIF});
  74. Var
  75. L,SL : Integer;
  76. begin
  77. SL:=System.Length(S);
  78. if SL>0 then
  79. begin
  80. L:=Length;
  81. Length:=L+SL;
  82. Move(S[1], FData[L],SL*SizeOf(SBChar));
  83. end;
  84. end;
  85. procedure TStringBuilder.DoAppend(const AValue: TSBCharArray; Idx, aCount: Integer
  86. );
  87. Var
  88. L : integer;
  89. begin
  90. L:=Length;
  91. CheckRange(Idx,aCount,System.Length(AValue));
  92. Length:=L+aCount;
  93. Move(AValue[Idx],FData[L],aCount*SizeOf(SBChar));
  94. end;
  95. procedure TStringBuilder.DoInsert(Index: Integer; const AValue: SBString);
  96. Var
  97. ShiftLen,LV : Integer;
  98. begin
  99. CheckRange(Index,0,Length-1);
  100. LV:=System.Length(AValue);
  101. ShiftLen:=Length-Index;
  102. Length:=Length+LV;
  103. Move(FData[Index],FData[Index+LV],ShiftLen*SizeOf(SBChar));
  104. Move(AValue[1],FData[Index],LV*SizeOf(SBChar));
  105. end;
  106. procedure TStringBuilder.DoInsert(Index: Integer; const AValue: TSBCharArray;
  107. StartIndex, SBCharCount: Integer);
  108. Var
  109. ShiftLen : Integer;
  110. begin
  111. CheckRange(Index,0,Length-1);
  112. CheckNegative(StartIndex,'StartIndex');
  113. CheckNegative(SBCharCount,'SBCharCount');
  114. CheckRange(StartIndex,SBCharCount,System.Length(AValue));
  115. Length:=Length+SBCharCount;
  116. ShiftLen:=Length-Index;
  117. if ShiftLen> 0 then
  118. Move(FData[Index], FData[Index+SBCharCount],ShiftLen*SizeOf(SBChar));
  119. Move(AValue[StartIndex],FData[Index],SBCharCount*SizeOf(SBChar));
  120. end;
  121. { Public routines for appending }
  122. function TStringBuilder.Append(const AValue: UInt64): TStringBuilder;
  123. begin
  124. DoAppend(IntToStr(AValue));
  125. Result:=self;
  126. end;
  127. function TStringBuilder.Append(const AValue: TSBCharArray): TStringBuilder;
  128. var
  129. I,L: Integer;
  130. begin
  131. I:=-1;
  132. L:=System.Length(AValue);
  133. If L=0 then
  134. Exit(Self);
  135. Repeat
  136. Inc(I);
  137. Until (I>=L) or (AValue[I]=#0);
  138. DoAppend(AValue,0,I);
  139. Result:=Self;
  140. end;
  141. function TStringBuilder.Append(const AValue: Single): TStringBuilder;
  142. begin
  143. DoAppend(FloatToStr(AValue));
  144. Result:=self;
  145. end;
  146. function TStringBuilder.Append(const AValue: Word): TStringBuilder;
  147. begin
  148. Append(IntToStr(AValue));
  149. Result:=self;
  150. end;
  151. function TStringBuilder.Append(const AValue: Cardinal): TStringBuilder;
  152. begin
  153. DoAppend(IntToStr(AValue));
  154. Result:=self;
  155. end;
  156. function TStringBuilder.Append(const AValue: SBChar; RepeatCount: Integer
  157. ): TStringBuilder;
  158. begin
  159. DoAppend(StringOfChar(AValue,RepeatCount));
  160. Result:=Self;
  161. end;
  162. function TStringBuilder.Append(const AValue: Shortint): TStringBuilder;
  163. begin
  164. DoAppend(IntToStr(AValue));
  165. Result:=Self;
  166. end;
  167. function TStringBuilder.Append(const AValue: SBChar): TStringBuilder;
  168. begin
  169. DoAppend(AValue);
  170. Result:=Self;
  171. end;
  172. function TStringBuilder.Append(const AValue: Currency): TStringBuilder;
  173. begin
  174. DoAppend(CurrToStr(AValue));
  175. Result:=Self;
  176. end;
  177. function TStringBuilder.Append(const AValue: Boolean): TStringBuilder;
  178. begin
  179. DoAppend(BoolToStr(AValue, True));
  180. Result:=Self;
  181. end;
  182. function TStringBuilder.Append(const AValue: Byte): TStringBuilder;
  183. begin
  184. DoAppend(IntToStr(AValue));
  185. Result:=Self;
  186. end;
  187. function TStringBuilder.Append(const AValue: Double): TStringBuilder;
  188. begin
  189. DoAppend(FloatToStr(AValue));
  190. Result:=Self;
  191. end;
  192. function TStringBuilder.Append(const AValue: Int64): TStringBuilder;
  193. begin
  194. DoAppend(IntToStr(AValue));
  195. Result:=Self;
  196. end;
  197. function TStringBuilder.Append(const AValue: TObject): TStringBuilder;
  198. begin
  199. DoAppend(AValue.ToString);
  200. Result:=Self;
  201. end;
  202. function TStringBuilder.Append(const AValue: Smallint): TStringBuilder;
  203. begin
  204. DoAppend(IntToStr(AValue));
  205. Result:=Self;
  206. end;
  207. function TStringBuilder.Append(const AValue: LongInt): TStringBuilder;
  208. begin
  209. DoAppend(IntToStr(AValue));
  210. Result:=Self;
  211. end;
  212. Function TStringBuilder.Append(const AValue: TSBCharArray; StartIndex, SBCharCount: Integer): TStringBuilder;
  213. begin
  214. DoAppend(AValue,StartIndex,SBCharCount);
  215. Result:=Self;
  216. end;
  217. Function TStringBuilder.Append(const AValue: SBString; StartIndex, Count: Integer): TStringBuilder;
  218. begin
  219. CheckRange(StartIndex,Count,System.Length(AValue));
  220. DoAppend(Copy(AValue,StartIndex+1,Count));
  221. Result:=Self;
  222. end;
  223. function TStringBuilder.Append(const AValue: PSBChar): TStringBuilder;
  224. begin
  225. DoAppend(AnsiString(AValue));
  226. Result:=Self;
  227. end;
  228. {$IFDEF SBUNICODE}
  229. function TStringBuilder.Append(const AValue: SBString): TStringBuilder;
  230. begin
  231. DoAppend(AValue);
  232. Result:=Self;
  233. end;
  234. {$ENDIF}
  235. function TStringBuilder.Append(const AValue: RawByteString): TStringBuilder;
  236. begin
  237. {$IFDEF SBUNICODE}
  238. DoAppend(SBString(AValue));
  239. {$ELSE}
  240. DoAppend(AValue);
  241. {$ENDIF}
  242. Result:=Self;
  243. end;
  244. function TStringBuilder.AppendFormat(const Fmt: SBString;
  245. const Args: array of const): TStringBuilder;
  246. begin
  247. DoAppend(Format(Fmt,Args));
  248. Result:=Self;
  249. end;
  250. function TStringBuilder.Append(const Fmt: SBString;
  251. const Args: array of const): TStringBuilder;
  252. begin
  253. DoAppend(Format(Fmt,Args));
  254. Result:=Self;
  255. end;
  256. function TStringBuilder.AppendLine: TStringBuilder;
  257. begin
  258. DoAppend(sLineBreak);
  259. Result:=Self;
  260. end;
  261. function TStringBuilder.AppendLine(const AValue: RawByteString): TStringBuilder;
  262. begin
  263. DoAppend(AValue);
  264. Result:=AppendLine();
  265. end;
  266. procedure TStringBuilder.Clear;
  267. begin
  268. Length:=0;
  269. Capacity:=DefaultCapacity;
  270. end;
  271. procedure TStringBuilder.CopyTo(SourceIndex: Integer;
  272. Var Destination: TSBCharArray; DestinationIndex: Integer; Count: Integer);
  273. begin
  274. CheckNegative(Count,'Count');
  275. CheckNegative(DestinationIndex,'DestinationIndex');
  276. CheckRange(DestinationIndex,Count,System.Length(Destination));
  277. if Count>0 then
  278. begin
  279. CheckRange(SourceIndex,Count,Length);
  280. Move(FData[SourceIndex],Destination[DestinationIndex],Count * SizeOf(SBChar));
  281. end;
  282. end;
  283. function TStringBuilder.EnsureCapacity(aCapacity: Integer): Integer;
  284. begin
  285. CheckRange(aCapacity,0,MaxCapacity);
  286. if Capacity<aCapacity then
  287. Capacity:=aCapacity;
  288. Result:=Capacity;
  289. end;
  290. function TStringBuilder.Equals(StringBuilder: TStringBuilder): Boolean;
  291. begin
  292. Result:=(StringBuilder<>nil);
  293. if Result then
  294. Result:=(Length=StringBuilder.Length)
  295. and (MaxCapacity=StringBuilder.MaxCapacity)
  296. and CompareMem(@FData[0],@StringBuilder.FData[0],Length*SizeOf(SBChar));
  297. end;
  298. procedure TStringBuilder.Grow;
  299. var
  300. NewCapacity: SizeInt;
  301. begin
  302. NewCapacity:=Capacity*2;
  303. if NewCapacity>MaxCapacity then
  304. NewCapacity:=MaxCapacity;
  305. Capacity:=NewCapacity;
  306. end;
  307. function TStringBuilder.Insert(Index: Integer; const AValue: TObject
  308. ): TStringBuilder;
  309. begin
  310. DoInsert(Index,AValue.ToString());
  311. Result:=Self;
  312. end;
  313. function TStringBuilder.Insert(Index: Integer; const AValue: Int64
  314. ): TStringBuilder;
  315. begin
  316. DoInsert(Index,IntToStr(AValue));
  317. Result:=Self;
  318. end;
  319. function TStringBuilder.Insert(Index: Integer; const AValue: Single
  320. ): TStringBuilder;
  321. begin
  322. DoInsert(Index,FloatToStr(AValue));
  323. Result:=Self;
  324. end;
  325. function TStringBuilder.Insert(Index: Integer; const AValue: SBString
  326. ): TStringBuilder;
  327. begin
  328. DoInsert(Index,AValue);
  329. Result:=Self;
  330. end;
  331. function TStringBuilder.Insert(Index: Integer; const AValue: Word
  332. ): TStringBuilder;
  333. begin
  334. DoInsert(Index,IntToStr(AValue));
  335. Result:=Self;
  336. end;
  337. function TStringBuilder.Insert(Index: Integer; const AValue: Shortint
  338. ): TStringBuilder;
  339. begin
  340. DoInsert(Index, IntToStr(AValue));
  341. Result:=Self;
  342. end;
  343. function TStringBuilder.Insert(Index: Integer; const AValue: Currency
  344. ): TStringBuilder;
  345. begin
  346. DoInsert(Index,CurrToStr(AValue));
  347. Result:=Self;
  348. end;
  349. function TStringBuilder.Insert(Index: Integer; const AValue: SBChar
  350. ): TStringBuilder;
  351. begin
  352. DoInsert(Index,AValue);
  353. Result:=Self;
  354. end;
  355. function TStringBuilder.Insert(Index: Integer; const AValue: Byte
  356. ): TStringBuilder;
  357. begin
  358. DoInsert(Index,IntToStr(AValue));
  359. Result:=Self;
  360. end;
  361. function TStringBuilder.Insert(Index: Integer; const AValue: Double
  362. ): TStringBuilder;
  363. begin
  364. DoInsert(Index,FloatToStr(AValue));
  365. Result:=Self;
  366. end;
  367. function TStringBuilder.Insert(Index: Integer; const AValue: LongInt
  368. ): TStringBuilder;
  369. begin
  370. DoInsert(Index,IntToStr(AValue));
  371. Result:=Self;
  372. end;
  373. function TStringBuilder.Insert(Index: Integer; const AValue: Smallint
  374. ): TStringBuilder;
  375. begin
  376. DoInsert(Index,IntToStr(AValue));
  377. Result:=Self;
  378. end;
  379. function TStringBuilder.Insert(Index: Integer; const AValue: Boolean
  380. ): TStringBuilder;
  381. begin
  382. DoInsert(Index,BoolToStr(AValue,True));
  383. Result:=Self;
  384. end;
  385. function TStringBuilder.Insert(Index: Integer; const AValue: SBString;
  386. const aRepeatCount: Integer): TStringBuilder;
  387. var
  388. I: Integer;
  389. begin
  390. for I:=0 to aRepeatCount-1 do
  391. DoInsert(Index,AValue);
  392. Result:=Self;
  393. end;
  394. function TStringBuilder.Insert(Index: Integer; const AValue: TSBCharArray
  395. ): TStringBuilder;
  396. begin
  397. DoInsert(Index,AValue,0,System.Length(AValue));
  398. Result:=Self;
  399. end;
  400. function TStringBuilder.Insert(Index: Integer; const AValue: TSBCharArray;
  401. startIndex: Integer; SBCharCount: Integer): TStringBuilder;
  402. begin
  403. DoInsert(Index,AValue,StartIndex,SBCharCount);
  404. Result:=Self;
  405. end;
  406. function TStringBuilder.Insert(Index: Integer; const AValue: Cardinal
  407. ): TStringBuilder;
  408. begin
  409. DoInsert(Index,IntToStr(AValue));
  410. Result:=self;
  411. end;
  412. function TStringBuilder.Insert(Index: Integer; const AValue: UInt64
  413. ): TStringBuilder;
  414. begin
  415. DoInsert(Index,IntToStr(AValue));
  416. Result:=self;
  417. end;
  418. procedure TStringBuilder.Shrink;
  419. begin
  420. if (Capacity div 4)>=Length then
  421. Capacity:=Capacity div 2;
  422. end;
  423. function TStringBuilder.Remove(StartIndex: Integer; RemLength: Integer
  424. ): TStringBuilder;
  425. Var
  426. MoveIndex : Integer;
  427. begin
  428. if (RemLength=0) then
  429. exit(Self);
  430. CheckNegative(RemLength,'RemLength');
  431. CheckRange(StartIndex,0,Length);
  432. MoveIndex:=StartIndex+RemLength;
  433. CheckRange(MoveIndex,0,Length-1);
  434. if (Length-Moveindex)>0 then
  435. Move(FData[MoveIndex],FData[StartIndex],(Length-MoveIndex)*SizeOf(SBChar));
  436. Length:=Length-RemLength;
  437. Shrink;
  438. Result:=Self;
  439. end;
  440. Function TStringBuilder.Replace(const OldValue, NewValue: SBRawString; StartIndex, Count: Integer): TStringBuilder;
  441. var
  442. Cur : PSBChar;
  443. CurIndex,MaxIndex : Integer;
  444. OldLen, NewLen, Delta : Integer;
  445. BC : SBChar;
  446. begin
  447. if Count=0 then
  448. Exit(Self);
  449. // Some checks.
  450. CheckNegative(StartIndex,'StartIndex');
  451. CheckNegative(Count,'Count');
  452. CheckRange(Startindex,Count,Length);
  453. // Init
  454. OldLen:=System.Length(OldValue);
  455. NewLen:=System.Length(NewValue);
  456. Delta:=NewLen-OldLen;
  457. MaxIndex:=StartIndex+Count;
  458. CurIndex:=StartIndex;
  459. BC:=OldValue[1];
  460. Cur:=@FData[StartIndex];
  461. // Loop
  462. while (CurIndex<Length-OldLen+1) and (CurIndex<MaxIndex) do
  463. begin
  464. if (Cur^=BC) then
  465. begin
  466. if 0=StrLComp(@FData[CurIndex],PSBChar(OldValue),OldLen) then
  467. begin
  468. // Do actual replace.
  469. DoReplace(CurIndex,OldValue,NewValue);
  470. Inc(CurIndex,NewLen-1);
  471. // DoReplace may have reallocated memory, so changed pointers, reset pointer
  472. Cur:=@FData[CurIndex];
  473. // The max index must be increased/decreased with Delta
  474. // 0123456789012
  475. // 'zzbczzedeafzz' replace('e','qqqq',6,3) -> zzbczzqqqqdqqqqafzz
  476. Inc(MaxIndex,Delta);
  477. end;
  478. end;
  479. Inc(CurIndex);
  480. Inc(Cur);
  481. end;
  482. Result:=Self;
  483. end;
  484. Function TStringBuilder.Replace(const OldChar, NewChar: SBChar; StartIndex,
  485. Count: Integer): TStringBuilder;
  486. var
  487. I : Integer;
  488. Cur : PSBChar;
  489. begin
  490. if Count=0 then
  491. Exit(Self);
  492. CheckNegative(StartIndex,'StartIndex');
  493. CheckNegative(Count,'Count');
  494. CheckRange(StartIndex,Count-1,Length);
  495. Cur:=@FData[StartIndex];
  496. For I:=1 to Count do
  497. begin
  498. if Cur^=OldChar then
  499. Cur^:=NewChar;
  500. Inc(Cur);
  501. end;
  502. Result:=Self;
  503. end;
  504. Function TStringBuilder.Replace(const OldChar, NewChar: SBChar): TStringBuilder;
  505. begin
  506. Result:=Replace(OldChar,NewChar,0,Length);
  507. end;
  508. Function TStringBuilder.Replace(const OldValue, NewValue: SBRawString): TStringBuilder;
  509. begin
  510. Result:=Replace(OldValue,NewValue,0,Length);
  511. end;
  512. procedure TStringBuilder.SetCapacity(AValue: Integer);
  513. begin
  514. if (AValue>FMaxCapacity) then
  515. Raise ERangeError.CreateFmt(SListCapacityError,[AValue]);
  516. if (AValue<Length) then
  517. Raise ERangeError.CreateFmt(SListCapacityError,[AValue]);
  518. System.SetLength(FData,AValue);
  519. end;
  520. function TStringBuilder.ToString: SBString;
  521. begin
  522. Result:=ToString(0,Length);
  523. end;
  524. function TStringBuilder.ToString(aStartIndex: Integer; aLength: Integer
  525. ): SBString;
  526. begin
  527. if (aLength=0) then
  528. Result:=''
  529. else
  530. begin
  531. CheckNegative(aStartIndex,'aStartIndex');
  532. CheckNegative(aLength,'aLength');
  533. CheckRange(aStartIndex,aLength,Length);
  534. System.SetLength(Result,aLength);
  535. Move(FData[aStartIndex],Result[1],aLength*SizeOf(SBChar));
  536. end;
  537. end;
  538. procedure TStringBuilder.DoReplace(Index: Integer; const Old, New: SBString);
  539. var
  540. NVLen,OVLen,OLen,Delta,TailStart: Integer;
  541. begin
  542. NVLen:=System.Length(New);
  543. OVLen:=System.Length(Old);
  544. Delta:=NVLen-OVLen;
  545. if (Delta<>0) then
  546. begin
  547. OLen:=Length;
  548. if (Delta>0) then
  549. Length:=OLen+Delta;
  550. TailStart:=Index+OVlen;
  551. Move(FData[TailStart],FData[Index+NVLen],(OLen-TailStart)*SizeOf(SBChar));
  552. if (Delta<0) then
  553. Length:=OLen+Delta;
  554. end;
  555. Move(New[1],FData[Index],NVLen*SizeOf(SBChar));
  556. end;