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.

287 lines
11 KiB

  1. unit uutlComparer;
  2. {$mode objfpc}{$H+}
  3. {$IFDEF UTL_NESTED_PROCVARS}
  4. {$modeswitch nestedprocvars}
  5. {$ENDIF}
  6. interface
  7. uses
  8. Classes, SysUtils,
  9. uutlInterfaces;
  10. type
  11. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  12. generic TutlEqualityComparer<T> = class(
  13. TInterfacedObject,
  14. specialize IutlEqualityComparer<T>)
  15. public
  16. function EqualityCompare(constref i1, i2: T): Boolean;
  17. end;
  18. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  19. generic TutlEqualityCompareEvent<T> = function(constref i1, i2: T): Boolean;
  20. generic TutlEqualityCompareEventO<T> = function(constref i1, i2: T): Boolean of object;
  21. {$IFDEF UTL_NESTED_PROCVARS}
  22. generic TutlEqualityCompareEventN<T> = function(constref i1, i2: T): Boolean is nested;
  23. {$ENDIF}
  24. generic TutlCallbackEqualityComparer<T> = class(
  25. TInterfacedObject,
  26. specialize IutlEqualityComparer<T>)
  27. private type
  28. TEqualityCompareEventType = (eetNormal, eetObject, eetNested);
  29. public type
  30. TCompareEvent = specialize TutlEqualityCompareEvent<T>;
  31. TCompareEventO = specialize TutlEqualityCompareEventO<T>;
  32. {$IFDEF UTL_NESTED_PROCVARS}
  33. TCompareEventN = specialize TutlEqualityCompareEventN<T>;
  34. {$ENDIF}
  35. strict private
  36. fType: TEqualityCompareEventType;
  37. fEvent: TCompareEvent;
  38. fEventO: TCompareEventO;
  39. {$IFDEF UTL_NESTED_PROCVARS}
  40. fEventN: TCompareEventN;
  41. {$ENDIF}
  42. public
  43. function EqualityCompare(constref i1, i2: T): Boolean;
  44. constructor Create(const aEvent: TCompareEvent); overload;
  45. constructor Create(const aEvent: TCompareEventO); overload;
  46. {$IFDEF UTL_NESTED_PROCVARS}
  47. constructor Create(const aEvent: TCompareEventN); overload;
  48. {$ENDIF}
  49. end;
  50. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. generic TutlComparer<T> = class(
  52. specialize TutlEqualityComparer<T>,
  53. specialize IutlEqualityComparer<T>,
  54. specialize IutlComparer<T>)
  55. public
  56. function Compare(constref i1, i2: T): Integer;
  57. end;
  58. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  59. generic TutlCompareEvent<T> = function(constref i1, i2: T): Integer;
  60. generic TutlCompareEventO<T> = function(constref i1, i2: T): Integer of object;
  61. {$IFDEF UTL_NESTED_PROCVARS}
  62. generic TutlCompareEventN<T> = function(constref i1, i2: T): Integer is nested;
  63. {$ENDIF}
  64. generic TutlCallbackComparer<T> = class(
  65. TInterfacedObject,
  66. specialize IutlEqualityComparer<T>,
  67. specialize IutlComparer<T>)
  68. private type
  69. TCompareEventType = (cetNormal, cetObject, cetNested);
  70. public type
  71. TCompareEvent = specialize TutlCompareEvent<T>;
  72. TCompareEventO = specialize TutlCompareEventO<T>;
  73. {$IFDEF UTL_NESTED_PROCVARS}
  74. TCompareEventN = specialize TutlCompareEventN<T>;
  75. {$ENDIF}
  76. strict private
  77. fType: TCompareEventType;
  78. fEvent: TCompareEvent;
  79. fEventO: TCompareEventO;
  80. {$IFDEF UTL_NESTED_PROCVARS}
  81. fEventN: TCompareEventN;
  82. {$ENDIF}
  83. public
  84. function Compare(constref i1, i2: T): Integer;
  85. function EqualityCompare(constref i1, i2: T): Boolean;
  86. constructor Create(const aEvent: TCompareEvent); overload;
  87. constructor Create(const aEvent: TCompareEventO); overload;
  88. {$IFDEF UTL_NESTED_PROCVARS}
  89. constructor Create(const aEvent: TCompareEventN); overload;
  90. {$ENDIF}
  91. end;
  92. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  93. generic TutlReverseComparer<T> = class(
  94. TInterfacedObject,
  95. specialize IutlEqualityComparer<T>,
  96. specialize IutlComparer<T>)
  97. public type
  98. IComparer = specialize IutlComparer<T>;
  99. private
  100. fComparer: IComparer;
  101. public
  102. function EqualityCompare(constref i1, i2: T): Boolean;
  103. function Compare(constref i1, i2: T): Integer;
  104. constructor Create(aComparer: IComparer);
  105. end;
  106. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  107. operator <(const i1, i2: TObject): Boolean; inline;
  108. operator >(const i1, i2: TObject): Boolean; inline;
  109. implementation
  110. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  111. //Helper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  112. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  113. operator <(const i1, i2: TObject): Boolean; inline;
  114. begin
  115. result := Pointer(i1) < Pointer(i2);
  116. end;
  117. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  118. operator >(const i1, i2: TObject): Boolean; inline;
  119. begin
  120. result := Pointer(i1) > Pointer(i2);
  121. end;
  122. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  123. //TutlEqualityComparer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  124. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  125. function TutlEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean;
  126. begin
  127. result := (i1 = i2);
  128. end;
  129. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  130. //TutlCallbackEqualityComparer///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  131. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. function TutlCallbackEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean;
  133. begin
  134. result := false;
  135. case fType of
  136. eetNormal: result := fEvent (i1, i2);
  137. eetObject: result := fEventO(i1, i2);
  138. {$IFDEF UTL_NESTED_PROCVARS}
  139. eetNested: result := fEventN(i1, i2);
  140. {$ENDIF}
  141. else
  142. raise Exception.Create('invalid or unknown callback type');
  143. end;
  144. end;
  145. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  146. constructor TutlCallbackEqualityComparer.Create(const aEvent: TCompareEvent);
  147. begin
  148. inherited Create;
  149. fType := eetNormal;
  150. fEvent := aEvent;
  151. end;
  152. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  153. constructor TutlCallbackEqualityComparer.Create(const aEvent: TCompareEventO);
  154. begin
  155. inherited Create;
  156. fType := eetObject;
  157. fEventO := aEvent;
  158. end;
  159. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  160. {$IFDEF UTL_NESTED_PROCVARS}
  161. constructor TutlCallbackEqualityComparer.Create(const aEvent: TCompareEventN);
  162. begin
  163. inherited Create;
  164. fType := eetNested;
  165. fEventN := aEvent;
  166. end;
  167. {$ENDIF}
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. //TutlComparer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  170. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  171. function TutlComparer.Compare(constref i1, i2: T): Integer;
  172. begin
  173. if (i1 < i2) then
  174. result := -1
  175. else if (i1 > i2) then
  176. result := 1
  177. else
  178. result := 0;
  179. end;
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. //TutlCallbackComparer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  182. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. function TutlCallbackComparer.Compare(constref i1, i2: T): Integer;
  184. begin
  185. result := 0;
  186. case fType of
  187. cetNormal: result := fEvent (i1, i2);
  188. cetObject: result := fEventO(i1, i2);
  189. {$IFDEF UTL_NESTED_PROCVARS}
  190. cetNested: result := fEventN(i1, i2);
  191. {$ENDIF}
  192. else
  193. raise Exception.Create('invalid or unknown callback type');
  194. end;
  195. end;
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. function TutlCallbackComparer.EqualityCompare(constref i1, i2: T): Boolean;
  198. begin
  199. result := (Compare(i1, i2) = 0);
  200. end;
  201. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  202. constructor TutlCallbackComparer.Create(const aEvent: TCompareEvent);
  203. begin
  204. inherited Create;
  205. fType := cetNormal;
  206. fEvent := aEvent;
  207. end;
  208. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  209. constructor TutlCallbackComparer.Create(const aEvent: TCompareEventO);
  210. begin
  211. inherited Create;
  212. fType := cetObject;
  213. fEventO := aEvent;
  214. end;
  215. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  216. {$IFDEF UTL_NESTED_PROCVARS}
  217. constructor TutlCallbackComparer.Create(const aEvent: TCompareEventN);
  218. begin
  219. inherited Create;
  220. fType := cetNested;
  221. fEventN := aEvent;
  222. end;
  223. {$ENDIF}
  224. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  225. //TutlReverseComparer///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  226. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  227. function TutlReverseComparer.EqualityCompare(constref i1, i2: T): Boolean;
  228. begin
  229. Result:= fComparer.EqualityCompare(i1, i2);
  230. end;
  231. function TutlReverseComparer.Compare(constref i1, i2: T): Integer;
  232. begin
  233. Result:= - fComparer.Compare(i1, i2);
  234. end;
  235. constructor TutlReverseComparer.Create(aComparer: IComparer);
  236. begin
  237. inherited Create;
  238. fComparer:= aComparer;
  239. end;
  240. end.