Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

1079 wiersze
41 KiB

  1. unit uutlEnumerator;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,
  6. uutlTypes, uutlInterfaces
  7. {$IFDEF UTL_ADVANCED_ENUMERATORS}
  8. , uutlAlgorithm
  9. {$ENDIF}
  10. ;
  11. type
  12. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  13. generic TutlEnumerator<T> = class(
  14. TInterfacedObject
  15. , specialize IEnumerator<T>
  16. , specialize IutlEnumerator<T>)
  17. public type
  18. TStatus = (
  19. stCreated,
  20. stReseted,
  21. stMoving,
  22. stFinished
  23. );
  24. {$IFDEF UTL_ENUMERATORS}
  25. TArray = specialize TutlArray<T>;
  26. IutlEnumerator = specialize IutlEnumerator<T>;
  27. IEqualityComparer = specialize IutlEqualityComparer<T>;
  28. {$IFDEF UTL_ADVANCED_ENUMERATORS}
  29. IComparer = specialize IutlComparer<T>;
  30. IFilter = specialize IutlFilter<T>;
  31. {$ENDIF}
  32. {$ENDIF}
  33. strict private
  34. fStatus: TStatus;
  35. fAutoReset: Boolean;
  36. protected
  37. function InternalMoveNext: Boolean; virtual; abstract;
  38. procedure InternalReset; virtual; abstract;
  39. public { IEnumerator }
  40. function GetCurrent: T; virtual; abstract;
  41. function MoveNext: Boolean;
  42. procedure Reset;
  43. {$IFDEF UTL_ENUMERATORS}
  44. public { IutlEnumerator }
  45. function GetEnumerator: IutlEnumerator; virtual;
  46. function Count (): Integer; virtual;
  47. function Any (): Boolean; virtual;
  48. function ToArray (): TArray; virtual;
  49. function Contains (constref aElement: T; aComparer: IEqualityComparer): Boolean; virtual;
  50. function Skip (aCount: Integer): IutlEnumerator; virtual;
  51. function Take (aCount: Integer): IutlEnumerator; virtual;
  52. function Concat (aEnumerator: IutlEnumerator): IutlEnumerator; virtual;
  53. function Reverse (): IutlEnumerator; virtual;
  54. {$IFDEF UTL_ADVANCED_ENUMERATORS}
  55. function Sort (aComparer: IComparer): IutlEnumerator; virtual;
  56. function Where (aFilter: IFilter): IutlEnumerator; virtual;
  57. function Distinct (aComparer: IComparer): IutlEnumerator; virtual;
  58. function Intersect(aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator; virtual;
  59. function Union (aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator; virtual;
  60. function Without (aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator; virtual;
  61. {$ENDIF}
  62. {$ENDIF}
  63. public
  64. property Status: TStatus read fStatus;
  65. property AutoReset: Boolean read fAutoReset write fAutoReset;
  66. constructor Create;
  67. end;
  68. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  69. generic TutlMemoryEnumerator<T> = class(
  70. specialize TutlEnumerator<T>)
  71. public type
  72. PT = ^T;
  73. strict private
  74. fMemory: PT;
  75. fReversed: Boolean;
  76. fCurrent: Integer;
  77. fFirst: Integer;
  78. fLast: Integer;
  79. protected
  80. property Memory: PT read fMemory write fMemory;
  81. property Reversed: Boolean read fReversed write fReversed;
  82. property First: Integer read fFirst write fFirst;
  83. property Last: Integer read fLast write fLast;
  84. protected { TutlEnumerator }
  85. function InternalMoveNext: Boolean; override;
  86. procedure InternalReset; override;
  87. public { IEnumerator }
  88. function GetCurrent: T; override;
  89. {$IFDEF UTL_ADVANCED_ENUMERATORS}
  90. public { IutlEnumerator }
  91. function Count (): Integer; override;
  92. function Any (): Boolean; override;
  93. function ToArray (): TArray; override;
  94. {$ENDIF}
  95. public
  96. constructor Create(
  97. const aMemory: PT;
  98. const aCount: Integer); overload;
  99. constructor Create(
  100. const aMemory: PT;
  101. const aReversed: Boolean;
  102. const aFirst: Integer;
  103. const aLast: Integer); overload;
  104. end;
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. generic TutlArrayEnumerator<T> = class(
  107. specialize TutlMemoryEnumerator<T>)
  108. {$IFNDEF UTL_ENUMERATORS}
  109. public type
  110. TArray = specialize TutlArray<T>;
  111. {$ENDIF}
  112. strict private
  113. fData: TArray;
  114. public { IEnumerator }
  115. procedure InternalReset; override;
  116. public
  117. property Data: TArray read fData write fData;
  118. constructor Create; overload;
  119. constructor Create(const aData: TArray); overload;
  120. constructor Create(const aData: TArray; const aReversed: Boolean); overload;
  121. end;
  122. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  123. {$IFDEF UTL_ENUMERATORS}
  124. generic TutlReverseEnumerator<T> = class(
  125. specialize TutlArrayEnumerator<T>)
  126. strict private
  127. fEnumerator: IutlEnumerator;
  128. public { IEnumerator }
  129. procedure InternalReset; override;
  130. public
  131. constructor Create(aEnumerator: IutlEnumerator); reintroduce;
  132. end;
  133. {$ENDIF}
  134. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  136. generic TutlSortEnumerator<T> = class(
  137. specialize TutlArrayEnumerator<T>)
  138. strict private
  139. fEnumerator: IutlEnumerator;
  140. fComparer: IComparer;
  141. public { IEnumerator }
  142. procedure InternalReset; override;
  143. public
  144. constructor Create(aEnumerator: IutlEnumerator; aComparer: IComparer); reintroduce;
  145. end;
  146. {$ENDIF}
  147. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  148. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  149. generic TutlDistinctEnumerator<T> = class(
  150. specialize TutlEnumerator<T>)
  151. strict private
  152. fEnumerator: IutlEnumerator;
  153. fComparer: IComparer;
  154. fCurrent: T;
  155. fData: array of T;
  156. protected { TutlEnumerator }
  157. function InternalMoveNext: Boolean; override;
  158. procedure InternalReset; override;
  159. public { IEnumerator }
  160. function GetCurrent: T; override;
  161. public
  162. constructor Create(aEnumerator: IutlEnumerator; aComparer: IComparer); reintroduce;
  163. end;
  164. {$ENDIF}
  165. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  166. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  167. generic TutlIntersectWithoutEnumerator<T> = class(
  168. specialize TutlEnumerator<T>)
  169. strict private
  170. fWithoutMode: Boolean;
  171. fEnumerator: IutlEnumerator;
  172. fOther: IutlEnumerator;
  173. fComparer: IComparer;
  174. fData: array of T;
  175. fCurrent: T;
  176. protected { TutlEnumerator }
  177. function InternalMoveNext: Boolean; override;
  178. procedure InternalReset; override;
  179. public { IEnumerator }
  180. function GetCurrent: T; override;
  181. public
  182. constructor Create(
  183. const aWithoutMode: Boolean;
  184. aEnumerator: IutlEnumerator;
  185. aOther: IutlEnumerator;
  186. aComparer: IComparer); reintroduce;
  187. end;
  188. {$ENDIF}
  189. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  190. {$IFDEF UTL_ENUMERATORS}
  191. generic TutlSkipTakeEnumerator<T> = class(
  192. specialize TutlEnumerator<T>)
  193. strict private
  194. fEnumerator: IutlEnumerator;
  195. fSkip: Integer; // greater than 0: skip X; lower than 0: skip none
  196. fTake: Integer; // greater than 0: take X; lower than 0: take all
  197. fCurrentSkip: Integer;
  198. fCurrentTake: Integer;
  199. protected { TutlEnumerator }
  200. function InternalMoveNext: Boolean; override;
  201. procedure InternalReset; override;
  202. public { IEnumerator }
  203. function GetCurrent: T; override;
  204. public
  205. constructor Create(aEnumerator: IutlEnumerator; const aSkip: Integer; const aTake: Integer);
  206. destructor Destroy; override;
  207. end;
  208. {$ENDIF}
  209. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  210. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  211. generic TutlWhereEnumerator<T> = class(
  212. specialize TutlEnumerator<T>)
  213. strict private
  214. fEnumerator: IutlEnumerator;
  215. fFilter: IFilter;
  216. protected { TutlEnumerator }
  217. function InternalMoveNext: Boolean; override;
  218. procedure InternalReset; override;
  219. public { IEnumerator }
  220. function GetCurrent: T; override;
  221. public
  222. constructor Create(aEnumerator: IutlEnumerator; aFilter: IFilter);
  223. destructor Destroy; override;
  224. end;
  225. {$ENDIF}
  226. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  227. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  228. generic TutlSelectEnumerator<Tin, Tout> = class(
  229. specialize TutlEnumerator<Tout>)
  230. public type
  231. IInEnumerator = specialize IutlEnumerator<Tin>;
  232. ISelector = specialize IutlSelector<Tin, Tout>;
  233. strict private
  234. fEnumerator: IInEnumerator;
  235. fSelector: ISelector;
  236. protected { TutlEnumerator }
  237. function InternalMoveNext: Boolean; override;
  238. procedure InternalReset; override;
  239. public { IEnumerator }
  240. function GetCurrent: Tout; override;
  241. public
  242. constructor Create(aEnumerator: IInEnumerator; aSelector: ISelector);
  243. destructor Destroy; override;
  244. end;
  245. {$ENDIF}
  246. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  247. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  248. generic TutlSelectManyEnumerator<Tin, Tout> = class(
  249. specialize TutlEnumerator<Tout>)
  250. public type
  251. IInEnumerator = specialize IutlEnumerator<Tin>;
  252. IOutEnumerator = specialize IutlEnumerator<Tout>;
  253. ISelector = specialize IutlSelector<Tin, IOutEnumerator>;
  254. strict private
  255. fEnumerator: IInEnumerator;
  256. fSelector: ISelector;
  257. fCurrent: IOutEnumerator;
  258. protected { TutlEnumerator }
  259. function InternalMoveNext: Boolean; override;
  260. procedure InternalReset; override;
  261. public { IEnumerator }
  262. function GetCurrent: Tout; override;
  263. public
  264. constructor Create(aEnumerator: IInEnumerator; aSelector: ISelector);
  265. destructor Destroy; override;
  266. end;
  267. {$ENDIF}
  268. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  269. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  270. generic TutlZipEnumerator<T, S> = class(
  271. specialize TutlEnumerator<specialize TutlPair<T, S>>)
  272. public type
  273. IEnumeratorT = specialize IutlEnumerator<T>;
  274. IEnumeratorS = specialize IutlEnumerator<S>;
  275. TPair = specialize TutlPair<T, S>;
  276. strict private
  277. fEnumeratorT: IEnumeratorT;
  278. fEnumeratorS: IEnumeratorS;
  279. protected { TutlEnumerator }
  280. function InternalMoveNext: Boolean; override;
  281. procedure InternalReset; override;
  282. public { IEnumerator }
  283. function GetCurrent: TPair; override;
  284. public
  285. constructor Create(aEnumeratorT: IEnumeratorT; aEnumeratorS: IEnumeratorS);
  286. destructor Destroy; override;
  287. end;
  288. {$ENDIF}
  289. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  290. {$IFDEF UTL_ENUMERATORS}
  291. generic TutlConcatEnumerator<T> = class(
  292. specialize TutlEnumerator<T>)
  293. public type
  294. TEnumerators = array of IutlEnumerator;
  295. strict private
  296. fEnumerators: TEnumerators;
  297. fCurrent: Integer;
  298. protected { TutlEnumerator }
  299. function InternalMoveNext: Boolean; override;
  300. procedure InternalReset; override;
  301. public { IEnumerator }
  302. function GetCurrent: T; override;
  303. public
  304. constructor Create(aEnumerators: TEnumerators);
  305. destructor Destroy; override;
  306. end;
  307. {$ENDIF}
  308. implementation
  309. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  310. //TutlEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  311. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  312. function TutlEnumerator.MoveNext: Boolean;
  313. begin
  314. if (fStatus = stCreated)
  315. or ( fAutoReset
  316. and (fStatus = stFinished))
  317. then
  318. Reset;
  319. result := InternalMoveNext;
  320. if not result then
  321. fStatus := stFinished
  322. else if (fStatus = stReseted) then
  323. fStatus := stMoving;
  324. end;
  325. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  326. procedure TutlEnumerator.Reset;
  327. begin
  328. InternalReset;
  329. fStatus := stReseted;
  330. end;
  331. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  332. {$IFDEF UTL_ENUMERATORS}
  333. function TutlEnumerator.GetEnumerator: IutlEnumerator;
  334. begin
  335. result := self;
  336. end;
  337. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  338. function TutlEnumerator.Count: Integer;
  339. begin
  340. result := 0;
  341. Reset;
  342. while MoveNext do
  343. inc(result);
  344. end;
  345. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  346. function TutlEnumerator.Any: Boolean;
  347. begin
  348. Reset;
  349. result := MoveNext;
  350. end;
  351. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  352. function TutlEnumerator.ToArray: TArray;
  353. var
  354. i: Integer;
  355. begin
  356. i := 0;
  357. SetLength(result, i);
  358. Reset;
  359. while MoveNext do begin
  360. inc(i);
  361. SetLength(result, i);
  362. result[i-1] := GetCurrent;
  363. end;
  364. end;
  365. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  366. function TutlEnumerator.Contains(constref aElement: T; aComparer: IEqualityComparer): Boolean;
  367. begin
  368. Reset;
  369. result := false;
  370. while MoveNext and not result do
  371. result := aComparer.EqualityCompare(aElement, GetCurrent);
  372. end;
  373. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  374. function TutlEnumerator.Skip(aCount: Integer): IutlEnumerator;
  375. begin
  376. result := specialize TutlSkipTakeEnumerator<T>.Create(self, aCount, -1);
  377. end;
  378. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  379. function TutlEnumerator.Take(aCount: Integer): IutlEnumerator;
  380. begin
  381. result := specialize TutlSkipTakeEnumerator<T>.Create(self, -1, aCount);
  382. end;
  383. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  384. function TutlEnumerator.Concat(aEnumerator: IutlEnumerator): IutlEnumerator;
  385. type
  386. TConcatEnumerator = specialize TutlConcatEnumerator<T>;
  387. begin
  388. result := TConcatEnumerator.Create(TConcatEnumerator.TEnumerators.Create(self, aEnumerator));
  389. end;
  390. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  391. function TutlEnumerator.Reverse: IutlEnumerator;
  392. begin
  393. result := specialize TutlReverseEnumerator<T>.Create(self);
  394. end;
  395. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  396. {$IFDEF UTL_ADVANCED_ENUMERATORS}
  397. function TutlEnumerator.Sort(aComparer: IComparer): IutlEnumerator;
  398. begin
  399. result := specialize TutlSortEnumerator<T>.Create(self, aComparer);
  400. end;
  401. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  402. function TutlEnumerator.Where(aFilter: IFilter): IutlEnumerator;
  403. begin
  404. result := specialize TutlWhereEnumerator<T>.Create(self, aFilter);
  405. end;
  406. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  407. function TutlEnumerator.Distinct(aComparer: IComparer): IutlEnumerator;
  408. begin
  409. result := specialize TutlDistinctEnumerator<T>.Create(self, aComparer);
  410. end;
  411. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  412. function TutlEnumerator.Intersect(aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator;
  413. begin
  414. result := specialize TutlIntersectWithoutEnumerator<T>.Create(false, self, aEnumerator, aComparer);
  415. end;
  416. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  417. function TutlEnumerator.Union(aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator;
  418. begin
  419. result := Concat(aEnumerator).Distinct(aComparer);
  420. end;
  421. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  422. function TutlEnumerator.Without(aEnumerator: IutlEnumerator; aComparer: IComparer): IutlEnumerator;
  423. begin
  424. result := specialize TutlIntersectWithoutEnumerator<T>.Create(true, self, aEnumerator, aComparer);
  425. end;
  426. {$ENDIF}
  427. {$ENDIF}
  428. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  429. constructor TutlEnumerator.Create;
  430. begin
  431. inherited Create;
  432. fStatus := stCreated;
  433. fAutoReset := false;
  434. end;
  435. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  436. //TutlMemoryEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  437. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  438. function TutlMemoryEnumerator.InternalMoveNext: Boolean;
  439. begin
  440. if fReversed
  441. then dec(fCurrent)
  442. else inc(fCurrent);
  443. result := (fFirst <= fCurrent) and (fCurrent <= fLast);
  444. end;
  445. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  446. procedure TutlMemoryEnumerator.InternalReset;
  447. begin
  448. if fReversed
  449. then fCurrent := fLast + 1
  450. else fCurrent := fFirst - 1;
  451. end;
  452. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  453. function TutlMemoryEnumerator.{%H-}GetCurrent: T;
  454. begin
  455. if not Assigned(fMemory) or (fCurrent < fFirst) or (fCurrent > fLast) then
  456. raise EInvalidOperation.Create('enumerator is not initialized');
  457. result := (fMemory + fCurrent)^;
  458. end;
  459. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  460. {$IFDEF UTL_ADVANCED_ENUMERATORS}
  461. function TutlMemoryEnumerator.Count: Integer;
  462. begin
  463. Reset;
  464. result := fLast - fFirst + 1;
  465. end;
  466. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  467. function TutlMemoryEnumerator.Any: Boolean;
  468. begin
  469. Reset;
  470. result := fFirst <= fLast;
  471. end;
  472. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  473. function TutlMemoryEnumerator.ToArray: TArray;
  474. var
  475. i: Integer;
  476. begin
  477. Reset;
  478. SetLength(result, fLast - fFirst + 1);
  479. if fReversed then begin
  480. for i := fFirst to fLast do
  481. result[i-fFirst] := fMemory[i];
  482. end else
  483. System.Move(fMemory^, result[0], SizeOf(T) * Length(result));
  484. end;
  485. {$ENDIF}
  486. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  487. constructor TutlMemoryEnumerator.Create(const aMemory: PT; const aCount: Integer);
  488. begin
  489. Create(aMemory, false, 0, aCount - 1);
  490. end;
  491. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  492. constructor TutlMemoryEnumerator.Create(
  493. const aMemory: PT;
  494. const aReversed: Boolean;
  495. const aFirst: Integer;
  496. const aLast: Integer);
  497. begin
  498. fMemory := aMemory;
  499. fReversed := aReversed;
  500. fFirst := aFirst;
  501. fLast := aLast;
  502. inherited Create;
  503. end;
  504. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  505. //TutlArrayEnumerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  506. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  507. procedure TutlArrayEnumerator.InternalReset;
  508. begin
  509. Memory := @fData[0];
  510. First := low(fData);
  511. Last := high(fData);
  512. inherited InternalReset;
  513. end;
  514. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  515. constructor TutlArrayEnumerator.Create;
  516. begin
  517. inherited Create(nil, false, 0, -1);
  518. end;
  519. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  520. constructor TutlArrayEnumerator.Create(const aData: TArray);
  521. begin
  522. Create(aData, false);
  523. end;
  524. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  525. constructor TutlArrayEnumerator.Create(const aData: TArray; const aReversed: Boolean);
  526. begin
  527. fData := aData;
  528. inherited Create(@fData[0], aReversed, low(fData), high(fData));
  529. end;
  530. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  531. //TutlReverseEnumerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  532. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  533. {$IFDEF UTL_ENUMERATORS}
  534. procedure TutlReverseEnumerator.InternalReset;
  535. begin
  536. Data := fEnumerator.ToArray;
  537. Reversed := true;
  538. inherited InternalReset;
  539. end;
  540. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  541. constructor TutlReverseEnumerator.Create(aEnumerator: IutlEnumerator);
  542. begin
  543. inherited Create;
  544. fEnumerator := aEnumerator;
  545. end;
  546. {$ENDIF}
  547. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  548. //TutlSortEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  549. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  550. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  551. procedure TutlSortEnumerator.InternalReset;
  552. type
  553. TBinarySearch = specialize TutlBinarySearch<T>;
  554. var
  555. c, i: Integer;
  556. tmp: T;
  557. arr: TArray;
  558. begin
  559. c := 0;
  560. SetLength(arr, c);
  561. fEnumerator.Reset;
  562. while fEnumerator.MoveNext do begin
  563. tmp := fEnumerator.GetCurrent;
  564. TBinarySearch.Search(arr[0], c, fComparer, tmp, i);
  565. inc(c);
  566. SetLength(arr, c);
  567. Move(arr[i], arr[i+1], SizeOf(T) * (Length(arr) - i - 1));
  568. FillByte(arr[i], SizeOf(T), 0);
  569. arr[i] := tmp;
  570. end;
  571. Data := arr;
  572. First := low(arr);
  573. Last := high(arr);
  574. inherited InternalReset;
  575. end;
  576. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  577. constructor TutlSortEnumerator.Create(aEnumerator: IutlEnumerator; aComparer: IComparer);
  578. begin
  579. inherited Create;
  580. fEnumerator := aEnumerator;
  581. fComparer := aComparer;
  582. end;
  583. {$ENDIF}
  584. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  585. //TutlDistinctEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  586. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  587. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  588. function TutlDistinctEnumerator.InternalMoveNext: Boolean;
  589. type
  590. TBinarySearch = specialize TutlBinarySearch<T>;
  591. var
  592. i: Integer;
  593. begin
  594. result := false;
  595. while not result and fEnumerator.MoveNext do begin
  596. fCurrent := fEnumerator.GetCurrent;
  597. result := not TBinarySearch.Search(fData[0], Length(fData), fComparer, fCurrent, i);
  598. if result then begin
  599. SetLength(fData, Length(fData) + 1);
  600. Move(fData[i], fData[i+1], SizeOf(T) * (Length(fData) - i - 1));
  601. FillByte(fData[i], SizeOf(T), 0);
  602. fData[i] := fCurrent;
  603. end;
  604. end;
  605. end;
  606. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  607. procedure TutlDistinctEnumerator.InternalReset;
  608. begin
  609. SetLength(fData, 0);
  610. fEnumerator.Reset;
  611. end;
  612. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  613. function TutlDistinctEnumerator.GetCurrent: T;
  614. begin
  615. result := fCurrent;
  616. end;
  617. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  618. constructor TutlDistinctEnumerator.Create(aEnumerator: IutlEnumerator; aComparer: IComparer);
  619. begin
  620. inherited Create;
  621. fEnumerator := aEnumerator;
  622. fComparer := aComparer;
  623. end;
  624. {$ENDIF}
  625. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  626. //TutlIntersectWithoutEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  627. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  628. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  629. function TutlIntersectWithoutEnumerator.InternalMoveNext: Boolean;
  630. type
  631. TBinarySearch = specialize TutlBinarySearch<T>;
  632. var
  633. i: Integer;
  634. begin
  635. result := false;
  636. while not result and fEnumerator.MoveNext do begin
  637. fCurrent := fEnumerator.GetCurrent;
  638. result := TBinarySearch.Search(fData[0], Length(fData), fComparer, fCurrent, i);
  639. if fWithoutMode then
  640. result := not result;
  641. end;
  642. end;
  643. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  644. procedure TutlIntersectWithoutEnumerator.InternalReset;
  645. begin
  646. fEnumerator.Reset;
  647. fData := fOther.Distinct(fComparer).Sort(fComparer).ToArray();
  648. end;
  649. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  650. function TutlIntersectWithoutEnumerator.GetCurrent: T;
  651. begin
  652. result := fCurrent;
  653. end;
  654. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  655. constructor TutlIntersectWithoutEnumerator.Create(
  656. const aWithoutMode: Boolean;
  657. aEnumerator: IutlEnumerator;
  658. aOther: IutlEnumerator;
  659. aComparer: IComparer);
  660. begin
  661. inherited Create;
  662. fWithoutMode := aWithoutMode;
  663. fEnumerator := aEnumerator;
  664. fOther := aOther;
  665. fComparer := aComparer;
  666. end;
  667. {$ENDIF}
  668. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  669. //TutlSkipTakeEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  670. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  671. {$IFDEF UTL_ENUMERATORS}
  672. function TutlSkipTakeEnumerator.InternalMoveNext: Boolean;
  673. begin
  674. while (fCurrentSkip > 0) and fEnumerator.MoveNext do
  675. dec(fCurrentSkip);
  676. result :=
  677. (fCurrentSkip <= 0)
  678. and (fCurrentTake <> 0)
  679. and fEnumerator.MoveNext;
  680. if (fCurrentTake > 0) then
  681. dec(fCurrentTake);
  682. end;
  683. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  684. procedure TutlSkipTakeEnumerator.InternalReset;
  685. begin
  686. fEnumerator.Reset;
  687. fCurrentSkip := fSkip;
  688. fCurrentTake := fTake;
  689. end;
  690. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  691. function TutlSkipTakeEnumerator.GetCurrent: T;
  692. begin
  693. result := fEnumerator.Current;
  694. end;
  695. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  696. constructor TutlSkipTakeEnumerator.Create(aEnumerator: IutlEnumerator; const aSkip: Integer; const aTake: Integer);
  697. begin
  698. if not Assigned(aEnumerator) then
  699. raise EArgumentNilException.Create('aEnumerator');
  700. inherited Create;
  701. fEnumerator := aEnumerator;
  702. fSkip := aSkip;
  703. fTake := aTake;
  704. fCurrentSkip := aSkip;
  705. fCurrentTake := aTake;
  706. end;
  707. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  708. destructor TutlSkipTakeEnumerator.Destroy;
  709. begin
  710. fEnumerator := nil;
  711. inherited Destroy;
  712. end;
  713. {$ENDIF}
  714. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  715. //TutlWhereEnumerator///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  716. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  717. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  718. function TutlWhereEnumerator.InternalMoveNext: Boolean;
  719. begin
  720. repeat
  721. result := fEnumerator.MoveNext;
  722. until not result or fFilter.Filter(fEnumerator.Current);
  723. end;
  724. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  725. procedure TutlWhereEnumerator.InternalReset;
  726. begin
  727. fEnumerator.Reset;
  728. end;
  729. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  730. function TutlWhereEnumerator.GetCurrent: T;
  731. begin
  732. result := fEnumerator.Current;
  733. end;
  734. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  735. constructor TutlWhereEnumerator.Create(aEnumerator: IutlEnumerator; aFilter: IFilter);
  736. begin
  737. if not Assigned(aEnumerator) then
  738. raise EArgumentNilException.Create('aEnumerator');
  739. if not Assigned(aFilter) then
  740. raise EArgumentNilException.Create('aFilter');
  741. inherited Create;
  742. fEnumerator := aEnumerator;
  743. fFilter := aFilter;
  744. end;
  745. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  746. destructor TutlWhereEnumerator.Destroy;
  747. begin
  748. fEnumerator := nil;
  749. fFilter := nil;
  750. inherited Destroy;
  751. end;
  752. {$ENDIF}
  753. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  754. //TutlSelectEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  755. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  756. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  757. function TutlSelectEnumerator.InternalMoveNext: Boolean;
  758. begin
  759. result := fEnumerator.MoveNext;
  760. end;
  761. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  762. procedure TutlSelectEnumerator.InternalReset;
  763. begin
  764. fEnumerator.Reset;
  765. end;
  766. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  767. function TutlSelectEnumerator.GetCurrent: Tout;
  768. begin
  769. result := fSelector.Select(fEnumerator.Current);
  770. end;
  771. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  772. constructor TutlSelectEnumerator.Create(aEnumerator: IInEnumerator; aSelector: ISelector);
  773. begin
  774. if not Assigned(aEnumerator) then
  775. raise EArgumentNilException.Create('aEnumerator');
  776. if not Assigned(aSelector) then
  777. raise EArgumentNilException.Create('aSelector');
  778. inherited Create;
  779. fEnumerator := aEnumerator;
  780. fSelector := aSelector;
  781. end;
  782. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  783. destructor TutlSelectEnumerator.Destroy;
  784. begin
  785. fEnumerator := nil;
  786. fSelector := nil;
  787. inherited Destroy;
  788. end;
  789. {$ENDIF}
  790. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  791. //TutlSelectManyEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  792. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  793. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  794. function TutlSelectManyEnumerator.InternalMoveNext: Boolean;
  795. begin
  796. result := false;
  797. while not result do begin
  798. while not Assigned(fCurrent) do begin
  799. if not fEnumerator.MoveNext then
  800. exit;
  801. fCurrent := fSelector.Select(fEnumerator.Current);
  802. if Assigned(fCurrent) then
  803. fCurrent.Reset;
  804. end;
  805. result := fCurrent.MoveNext;
  806. if not result then
  807. fCurrent := nil;
  808. end;
  809. end;
  810. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  811. procedure TutlSelectManyEnumerator.InternalReset;
  812. begin
  813. fEnumerator.Reset;
  814. fCurrent := nil;
  815. end;
  816. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  817. function TutlSelectManyEnumerator.GetCurrent: Tout;
  818. begin
  819. if not Assigned(fCurrent) then
  820. raise EInvalidOperation.Create('enumerator is not initialized');
  821. result := fCurrent.GetCurrent;
  822. end;
  823. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  824. constructor TutlSelectManyEnumerator.Create(aEnumerator: IInEnumerator; aSelector: ISelector);
  825. begin
  826. inherited Create;
  827. fEnumerator := aEnumerator;
  828. fSelector := aSelector;
  829. fCurrent := nil;
  830. end;
  831. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  832. destructor TutlSelectManyEnumerator.Destroy;
  833. begin
  834. fCurrent := nil;
  835. fEnumerator := nil;
  836. fSelector := nil;
  837. inherited Destroy;
  838. end;
  839. {$ENDIF}
  840. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  841. {$IF DEFINED(UTL_ENUMERATORS) AND DEFINED(UTL_ADVANCED_ENUMERATORS)}
  842. function TutlZipEnumerator.InternalMoveNext: Boolean;
  843. begin
  844. result := fEnumeratorT.MoveNext and fEnumeratorS.MoveNext;
  845. end;
  846. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  847. procedure TutlZipEnumerator.InternalReset;
  848. begin
  849. fEnumeratorT.Reset;
  850. fEnumeratorS.Reset;
  851. end;
  852. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  853. function TutlZipEnumerator.GetCurrent: TPair;
  854. begin
  855. result.First := fEnumeratorT.GetCurrent;
  856. result.Second := fEnumeratorS.GetCurrent;
  857. end;
  858. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  859. constructor TutlZipEnumerator.Create(aEnumeratorT: IEnumeratorT; aEnumeratorS: IEnumeratorS);
  860. begin
  861. inherited Create;
  862. fEnumeratorT := aEnumeratorT;
  863. fEnumeratorS := aEnumeratorS;
  864. end;
  865. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  866. destructor TutlZipEnumerator.Destroy;
  867. begin
  868. fEnumeratorT := nil;
  869. fEnumeratorS := nil;
  870. inherited Destroy;
  871. end;
  872. {$ENDIF}
  873. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  874. //TutlConcatEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  875. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  876. {$IFDEF UTL_ENUMERATORS}
  877. function TutlConcatEnumerator.InternalMoveNext: Boolean;
  878. begin
  879. if (fCurrent < 0) then begin
  880. fCurrent := 0;
  881. fEnumerators[fCurrent].Reset;
  882. end;
  883. result := false;
  884. while not result and (fCurrent <= high(fEnumerators)) and not fEnumerators[fCurrent].MoveNext do begin
  885. inc(fCurrent);
  886. if (fCurrent > high(fEnumerators)) then
  887. exit;
  888. fEnumerators[fCurrent].Reset;
  889. end;
  890. result := (fCurrent <= high(fEnumerators));
  891. end;
  892. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  893. procedure TutlConcatEnumerator.InternalReset;
  894. begin
  895. fCurrent := -1;
  896. end;
  897. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  898. function TutlConcatEnumerator.{%H-}GetCurrent: T;
  899. begin
  900. if (fCurrent < low(fEnumerators)) or (fCurrent > high(fEnumerators)) then
  901. raise EInvalidOperation.Create('enumerator is not initialized');
  902. result := fEnumerators[fCurrent].Current;
  903. end;
  904. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  905. constructor TutlConcatEnumerator.Create(aEnumerators: TEnumerators);
  906. begin
  907. inherited Create;
  908. fCurrent := -1;
  909. fEnumerators := aEnumerators;
  910. end;
  911. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  912. destructor TutlConcatEnumerator.Destroy;
  913. var
  914. i: Integer;
  915. begin
  916. for i := low(fEnumerators) to high(fEnumerators) do
  917. fEnumerators [i] := nil;
  918. SetLength(fEnumerators, 0);
  919. inherited Destroy;
  920. end;
  921. {$ENDIF}
  922. end.