You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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