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.

437 lines
21 KiB

  1. unit uutlLinq;
  2. {$mode objfpc}{$H+}
  3. {$IFDEF UTL_NESTED_PROCVARS}
  4. {$modeswitch nestedprocvars}
  5. {$ENDIF}
  6. interface
  7. {$IFDEF UTL_ENUMERATORS}
  8. uses
  9. Classes, SysUtils,
  10. uutlTypes, uutlInterfaces, uutlComparer, uutlFilter;
  11. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  12. generic function utlCount<T>(
  13. constref aEnumerator: specialize IutlEnumerator<T>): Integer; inline;
  14. generic function utlAny<T>(
  15. constref aEnumerator: specialize IutlEnumerator<T>): Boolean; inline;
  16. generic function utlToArray<T>(
  17. constref aEnumerator: specialize IutlEnumerator<T>): specialize TutlArray<T>; inline;
  18. generic function utlContains<T>(
  19. constref aEnumerator: specialize IutlEnumerator<T>;
  20. constref aElement: T): Boolean; inline; overload;
  21. generic function utlContains<T>(
  22. constref aEnumerator: specialize IutlEnumerator<T>;
  23. constref aElement: T;
  24. constref aComparer: specialize IutlEqualityComparer<T>): Boolean; inline; overload;
  25. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  26. generic function utlSkip<T>(
  27. constref aEnumerator: specialize IutlEnumerator<T>;
  28. const aSkip: Integer): specialize IutlEnumerator<T>; inline;
  29. generic function utlTake<T>(
  30. constref aEnumerator: specialize IutlEnumerator<T>;
  31. const aTake: Integer): specialize IutlEnumerator<T>; inline;
  32. generic function utlConcat<T>(
  33. constref aEnumerator1, aEnumerator2: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>; inline; overload;
  34. generic function utlConcat<T>(
  35. constref aEnumerators: specialize TutlArray<specialize IutlEnumerator<T>>): specialize IutlEnumerator<T>; inline; overload;
  36. generic function utlReverse<T>(
  37. constref aEnumerator: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>; inline;
  38. {$IFDEF UTL_ADVANCED_ENUMERATORS}
  39. generic function utlSort<T>(
  40. constref aEnumerator: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>; inline; overload;
  41. generic function utlSort<T>(
  42. constref aEnumerator: specialize IutlEnumerator<T>;
  43. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>; inline; overload;
  44. generic function utlWhere<T>(
  45. constref aEnumerator: specialize IutlEnumerator<T>;
  46. constref aFilter: specialize IutlFilter<T>): specialize IutlEnumerator<T>; inline; overload;
  47. generic function utlWhere<T>(
  48. constref aEnumerator: specialize IutlEnumerator<T>;
  49. constref aFilter: specialize TutlFilterEvent<T>): specialize IutlEnumerator<T>; inline; overload;
  50. generic function utlWhere<T>(
  51. constref aEnumerator: specialize IutlEnumerator<T>;
  52. constref aFilter: specialize TutlFilterEventO<T>): specialize IutlEnumerator<T>; inline; overload;
  53. {$IFDEF UTL_NESTED_PROCVARS}
  54. generic function utlWhere<T>(
  55. constref aEnumerator: specialize IutlEnumerator<T>;
  56. constref aFilter: specialize TutlFilterEventN<T>): specialize IutlEnumerator<T>; inline; overload;
  57. {$ENDIF}
  58. generic function utlDistinct<T>(
  59. constref aEnumerator: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>; inline; overload;
  60. generic function utlDistinct<T>(
  61. constref aEnumerator: specialize IutlEnumerator<T>;
  62. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>; inline; overload;
  63. generic function utlIntersect<T>(
  64. constref aEnumerator1: specialize IutlEnumerator<T>;
  65. constref aEnumerator2: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>; inline; overload;
  66. generic function utlIntersect<T>(
  67. constref aEnumerator1: specialize IutlEnumerator<T>;
  68. constref aEnumerator2: specialize IutlEnumerator<T>;
  69. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>; inline; overload;
  70. generic function utlUnion<T>(
  71. constref aEnumerator1: specialize IutlEnumerator<T>;
  72. constref aEnumerator2: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>; inline; overload;
  73. generic function utlUnion<T>(
  74. constref aEnumerator1: specialize IutlEnumerator<T>;
  75. constref aEnumerator2: specialize IutlEnumerator<T>;
  76. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>; inline; overload;
  77. generic function utlWithout<T>(
  78. constref aEnumerator1: specialize IutlEnumerator<T>;
  79. constref aEnumerator2: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>; inline; overload;
  80. generic function utlWithout<T>(
  81. constref aEnumerator1: specialize IutlEnumerator<T>;
  82. constref aEnumerator2: specialize IutlEnumerator<T>;
  83. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>; inline; overload;
  84. generic function utlSelect<T, S>(
  85. constref aEnumerator: specialize IutlEnumerator<T>;
  86. constref aSelector: specialize IutlSelector<T, S>): specialize IutlEnumerator<S>; inline; overload;
  87. generic function utlSelect<T, S>(
  88. constref aEnumerator: specialize IutlEnumerator<T>;
  89. constref aSelector: specialize TutlSelectEvent<T, S>): specialize IutlEnumerator<S>; inline; overload;
  90. generic function utlSelect<T, S>(
  91. constref aEnumerator: specialize IutlEnumerator<T>;
  92. constref aSelector: specialize TutlSelectEventO<T, S>): specialize IutlEnumerator<S>; inline; overload;
  93. {$IFDEF UTL_NESTED_PROCVARS}
  94. generic function utlSelect<T, S>(
  95. constref aEnumerator: specialize IutlEnumerator<T>;
  96. constref aSelector: specialize TutlSelectEventN<T, S>): specialize IutlEnumerator<S>; inline; overload;
  97. {$ENDIF}
  98. generic function utlSelectMany<T, S>(
  99. constref aEnumerator: specialize IutlEnumerator<T>;
  100. constref aSelector: specialize IutlSelector<T, specialize IutlEnumerator<S>>): specialize IutlEnumerator<S>; inline; overload;
  101. generic function utlSelectMany<T, S>(
  102. constref aEnumerator: specialize IutlEnumerator<T>;
  103. constref aSelector: specialize TutlSelectEvent<T, specialize IutlEnumerator<S>>): specialize IutlEnumerator<S>; inline; overload;
  104. generic function utlSelectMany<T, S>(
  105. constref aEnumerator: specialize IutlEnumerator<T>;
  106. constref aSelector: specialize TutlSelectEventO<T, specialize IutlEnumerator<S>>): specialize IutlEnumerator<S>; inline; overload;
  107. {$IFDEF UTL_NESTED_PROCVARS}
  108. generic function utlSelectMany<T, S>(
  109. constref aEnumerator: specialize IutlEnumerator<T>;
  110. constref aSelector: specialize TutlSelectEventN<T, specialize IutlEnumerator<S>>): specialize IutlEnumerator<S>; inline; overload;
  111. {$ENDIF}
  112. generic function utlZip<T, S>(
  113. constref aEnumerator1: specialize IutlEnumerator<T>;
  114. constref aEnumerator2: specialize IutlEnumerator<S>): specialize IutlEnumerator<specialize TutlPair<T, S>>;
  115. {$ENDIF}
  116. {$ENDIF}
  117. implementation
  118. {$IFDEF UTL_ENUMERATORS}
  119. uses
  120. uutlEnumerator;
  121. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  122. //utlLinq///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  123. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  124. generic function utlCount<T>(
  125. constref aEnumerator: specialize IutlEnumerator<T>): Integer;
  126. begin
  127. result := aEnumerator.Count;
  128. end;
  129. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  130. generic function utlAny<T>(
  131. constref aEnumerator: specialize IutlEnumerator<T>): Boolean;
  132. begin
  133. result := aEnumerator.Any;
  134. end;
  135. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  136. generic function utlToArray<T>(
  137. constref aEnumerator: specialize IutlEnumerator<T>): specialize TutlArray<T>;
  138. begin
  139. result := aEnumerator.ToArray;
  140. end;
  141. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  142. generic function utlContains<T>(
  143. constref aEnumerator: specialize IutlEnumerator<T>;
  144. constref aElement: T): Boolean;
  145. begin
  146. result := aEnumerator.Contains(aElement, specialize TutlEqualityComparer<T>.Create);
  147. end;
  148. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  149. generic function utlContains<T>(
  150. constref aEnumerator: specialize IutlEnumerator<T>;
  151. constref aElement: T;
  152. constref aComparer: specialize IutlEqualityComparer<T>): Boolean;
  153. begin
  154. result := aEnumerator.Contains(aElement, aComparer);
  155. end;
  156. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  157. generic function utlSkip<T>(
  158. constref aEnumerator: specialize IutlEnumerator<T>;
  159. const aSkip: Integer): specialize IutlEnumerator<T>;
  160. begin
  161. result := aEnumerator.Skip(aSkip);
  162. end;
  163. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  164. generic function utlTake<T>(
  165. constref aEnumerator: specialize IutlEnumerator<T>;
  166. const aTake: Integer): specialize IutlEnumerator<T>;
  167. begin
  168. result := aEnumerator.Take(aTake);
  169. end;
  170. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  171. generic function utlConcat<T>(
  172. constref aEnumerator1, aEnumerator2: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>;
  173. type
  174. TConcatEnumerator = specialize TutlConcatEnumerator<T>;
  175. begin
  176. result := TConcatEnumerator.Create(TConcatEnumerator.TEnumerators.Create(aEnumerator1, aEnumerator2));
  177. end;
  178. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  179. generic function utlConcat<T>(
  180. constref aEnumerators: specialize TutlArray<specialize IutlEnumerator<T>>): specialize IutlEnumerator<T>;
  181. type
  182. TConcatEnumerator = specialize TutlConcatEnumerator<T>;
  183. begin
  184. result := TConcatEnumerator.Create(aEnumerators);
  185. end;
  186. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  187. generic function utlReverse<T>(
  188. constref aEnumerator: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>;
  189. begin
  190. result := aEnumerator.Reverse;
  191. end;
  192. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  193. {$IFDEF UTL_ADVANCED_ENUMERATORS}
  194. generic function utlSort<T>(
  195. constref aEnumerator: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>;
  196. begin
  197. result := aEnumerator.Sort(specialize TutlComparer<T>.Create);
  198. end;
  199. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  200. generic function utlSort<T>(
  201. constref aEnumerator: specialize IutlEnumerator<T>;
  202. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>;
  203. begin
  204. result := aEnumerator.Sort(aComparer);
  205. end;
  206. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  207. generic function utlWhere<T>(
  208. constref aEnumerator: specialize IutlEnumerator<T>;
  209. constref aFilter: specialize IutlFilter<T>): specialize IutlEnumerator<T>;
  210. begin
  211. result := aEnumerator.Where(aFilter);
  212. end;
  213. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  214. generic function utlWhere<T>(
  215. constref aEnumerator: specialize IutlEnumerator<T>;
  216. constref aFilter: specialize TutlFilterEvent<T>): specialize IutlEnumerator<T>;
  217. begin
  218. result := aEnumerator.Where(specialize TutlCallbackFilter<T>.Create(aFilter));
  219. end;
  220. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  221. generic function utlWhere<T>(
  222. constref aEnumerator: specialize IutlEnumerator<T>;
  223. constref aFilter: specialize TutlFilterEventO<T>): specialize IutlEnumerator<T>;
  224. begin
  225. result := aEnumerator.Where(specialize TutlCallbackFilter<T>.Create(aFilter));
  226. end;
  227. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  228. {$IFDEF UTL_NESTED_PROCVARS}
  229. generic function utlWhere<T>(
  230. constref aEnumerator: specialize IutlEnumerator<T>;
  231. constref aFilter: specialize TutlFilterEventN<T>): specialize IutlEnumerator<T>;
  232. begin
  233. result := aEnumerator.Where(specialize TutlCallbackFilter<T>.Create(aFilter));
  234. end;
  235. {$ENDIF}
  236. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  237. generic function utlDistinct<T>(
  238. constref aEnumerator: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>;
  239. begin
  240. result := aEnumerator.Distinct(specialize TutlComparer<T>.Create);
  241. end;
  242. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  243. generic function utlDistinct<T>(
  244. constref aEnumerator: specialize IutlEnumerator<T>;
  245. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>;
  246. begin
  247. result := aEnumerator.Distinct(aComparer);
  248. end;
  249. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  250. generic function utlIntersect<T>(
  251. constref aEnumerator1: specialize IutlEnumerator<T>;
  252. constref aEnumerator2: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>;
  253. begin
  254. result := aEnumerator1.Intersect(aEnumerator2, specialize TutlComparer<T>.Create);
  255. end;
  256. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  257. generic function utlIntersect<T>(
  258. constref aEnumerator1: specialize IutlEnumerator<T>;
  259. constref aEnumerator2: specialize IutlEnumerator<T>;
  260. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>;
  261. begin
  262. result := aEnumerator1.Intersect(aEnumerator2, aComparer);
  263. end;
  264. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  265. generic function utlUnion<T>(
  266. constref aEnumerator1: specialize IutlEnumerator<T>;
  267. constref aEnumerator2: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>;
  268. begin
  269. result := aEnumerator1.Union(aEnumerator2, specialize TutlComparer<T>.Create);
  270. end;
  271. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  272. generic function utlUnion<T>(
  273. constref aEnumerator1: specialize IutlEnumerator<T>;
  274. constref aEnumerator2: specialize IutlEnumerator<T>;
  275. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>;
  276. begin
  277. result := aEnumerator1.Union(aEnumerator2, aComparer);
  278. end;
  279. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  280. generic function utlWithout<T>(
  281. constref aEnumerator1: specialize IutlEnumerator<T>;
  282. constref aEnumerator2: specialize IutlEnumerator<T>): specialize IutlEnumerator<T>;
  283. begin
  284. result := aEnumerator1.Without(aEnumerator2, specialize TutlComparer<T>.Create);
  285. end;
  286. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  287. generic function utlWithout<T>(
  288. constref aEnumerator1: specialize IutlEnumerator<T>;
  289. constref aEnumerator2: specialize IutlEnumerator<T>;
  290. constref aComparer: specialize IutlComparer<T>): specialize IutlEnumerator<T>;
  291. begin
  292. result := aEnumerator1.Without(aEnumerator2, aComparer);
  293. end;
  294. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  295. generic function utlSelect<T, S>(
  296. constref aEnumerator: specialize IutlEnumerator<T>;
  297. constref aSelector: specialize IutlSelector<T, S>): specialize IutlEnumerator<S>;
  298. begin
  299. result := specialize TutlSelectEnumerator<T, S>.Create(aEnumerator, aSelector);
  300. end;
  301. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  302. generic function utlSelect<T, S>(
  303. constref aEnumerator: specialize IutlEnumerator<T>;
  304. constref aSelector: specialize TutlSelectEvent<T, S>): specialize IutlEnumerator<S>;
  305. begin
  306. result := specialize TutlSelectEnumerator<T, S>.Create(aEnumerator, specialize TutlCallbackSelector<T, S>.Create(aSelector));
  307. end;
  308. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  309. generic function utlSelect<T, S>(
  310. constref aEnumerator: specialize IutlEnumerator<T>;
  311. constref aSelector: specialize TutlSelectEventO<T, S>): specialize IutlEnumerator<S>;
  312. begin
  313. result := specialize TutlSelectEnumerator<T, S>.Create(aEnumerator, specialize TutlCallbackSelector<T, S>.Create(aSelector));
  314. end;
  315. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  316. {$IFDEF UTL_NESTED_PROCVARS}
  317. generic function utlSelect<T, S>(
  318. constref aEnumerator: specialize IutlEnumerator<T>;
  319. constref aSelector: specialize TutlSelectEventN<T, S>): specialize IutlEnumerator<S>;
  320. begin
  321. result := specialize TutlSelectEnumerator<T, S>.Create(aEnumerator, specialize TutlCallbackSelector<T, S>.Create(aSelector));
  322. end;
  323. {$ENDIF}
  324. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  325. generic function utlSelectMany<T, S>(
  326. constref aEnumerator: specialize IutlEnumerator<T>;
  327. constref aSelector: specialize IutlSelector<T, specialize IutlEnumerator<S>>): specialize IutlEnumerator<S>;
  328. begin
  329. result := specialize TutlSelectManyEnumerator<T, S>.Create(aEnumerator, aSelector);
  330. end;
  331. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  332. generic function utlSelectMany<T, S>(
  333. constref aEnumerator: specialize IutlEnumerator<T>;
  334. constref aSelector: specialize TutlSelectEvent<T, specialize IutlEnumerator<S>>): specialize IutlEnumerator<S>;
  335. begin
  336. result := specialize TutlSelectManyEnumerator<T, S>.Create(aEnumerator, specialize TutlCallbackSelector<T, specialize IutlEnumerator<S>>.Create(aSelector));
  337. end;
  338. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  339. generic function utlSelectMany<T, S>(
  340. constref aEnumerator: specialize IutlEnumerator<T>;
  341. constref aSelector: specialize TutlSelectEventO<T, specialize IutlEnumerator<S>>): specialize IutlEnumerator<S>;
  342. begin
  343. result := specialize TutlSelectManyEnumerator<T, S>.Create(aEnumerator, specialize TutlCallbackSelector<T, specialize IutlEnumerator<S>>.Create(aSelector));
  344. end;
  345. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  346. {$IFDEF UTL_NESTED_PROCVARS}
  347. generic function utlSelectMany<T, S>(
  348. constref aEnumerator: specialize IutlEnumerator<T>;
  349. constref aSelector: specialize TutlSelectEventN<T, specialize IutlEnumerator<S>>): specialize IutlEnumerator<S>;
  350. begin
  351. result := specialize TutlSelectManyEnumerator<T, S>.Create(aEnumerator, specialize TutlCallbackSelector<T, specialize IutlEnumerator<S>>.Create(aSelector));
  352. end;
  353. {$ENDIF}
  354. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  355. generic function utlZip<T, S>(
  356. constref aEnumerator1: specialize IutlEnumerator<T>;
  357. constref aEnumerator2: specialize IutlEnumerator<S>): specialize IutlEnumerator<specialize TutlPair<T, S>>;
  358. begin
  359. result := specialize TutlZipEnumerator<T, S>.Create(aEnumerator1, aEnumerator2);
  360. end;
  361. {$ENDIF}
  362. {$ENDIF}
  363. end.