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.

249 lines
9.8 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. operator <(const i1, i2: TObject): Boolean; inline;
  94. operator >(const i1, i2: TObject): Boolean; inline;
  95. implementation
  96. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  97. //Helper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  99. operator <(const i1, i2: TObject): Boolean; inline;
  100. begin
  101. result := Pointer(i1) < Pointer(i2);
  102. end;
  103. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  104. operator >(const i1, i2: TObject): Boolean; inline;
  105. begin
  106. result := Pointer(i1) > Pointer(i2);
  107. end;
  108. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  109. //TutlEqualityComparer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  110. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  111. function TutlEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean;
  112. begin
  113. result := (i1 = i2);
  114. end;
  115. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. //TutlCallbackEqualityComparer///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  117. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  118. function TutlCallbackEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean;
  119. begin
  120. result := false;
  121. case fType of
  122. eetNormal: result := fEvent (i1, i2);
  123. eetObject: result := fEventO(i1, i2);
  124. {$IFDEF UTL_NESTED_PROCVARS}
  125. eetNested: result := fEventN(i1, i2);
  126. {$ENDIF}
  127. else
  128. raise Exception.Create('invalid or unknown callback type');
  129. end;
  130. end;
  131. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. constructor TutlCallbackEqualityComparer.Create(const aEvent: TCompareEvent);
  133. begin
  134. inherited Create;
  135. fType := eetNormal;
  136. fEvent := aEvent;
  137. end;
  138. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  139. constructor TutlCallbackEqualityComparer.Create(const aEvent: TCompareEventO);
  140. begin
  141. inherited Create;
  142. fType := eetObject;
  143. fEventO := aEvent;
  144. end;
  145. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  146. {$IFDEF UTL_NESTED_PROCVARS}
  147. constructor TutlCallbackEqualityComparer.Create(const aEvent: TCompareEventN);
  148. begin
  149. inherited Create;
  150. fType := eetNested;
  151. fEventN := aEvent;
  152. end;
  153. {$ENDIF}
  154. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  155. //TutlComparer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  156. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  157. function TutlComparer.Compare(constref i1, i2: T): Integer;
  158. begin
  159. if (i1 < i2) then
  160. result := -1
  161. else if (i1 > i2) then
  162. result := 1
  163. else
  164. result := 0;
  165. end;
  166. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  167. //TutlCallbackComparer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. function TutlCallbackComparer.Compare(constref i1, i2: T): Integer;
  170. begin
  171. result := 0;
  172. case fType of
  173. cetNormal: result := fEvent (i1, i2);
  174. cetObject: result := fEventO(i1, i2);
  175. {$IFDEF UTL_NESTED_PROCVARS}
  176. cetNested: result := fEventN(i1, i2);
  177. {$ENDIF}
  178. else
  179. raise Exception.Create('invalid or unknown callback type');
  180. end;
  181. end;
  182. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. function TutlCallbackComparer.EqualityCompare(constref i1, i2: T): Boolean;
  184. begin
  185. result := (Compare(i1, i2) = 0);
  186. end;
  187. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  188. constructor TutlCallbackComparer.Create(const aEvent: TCompareEvent);
  189. begin
  190. inherited Create;
  191. fType := cetNormal;
  192. fEvent := aEvent;
  193. end;
  194. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  195. constructor TutlCallbackComparer.Create(const aEvent: TCompareEventO);
  196. begin
  197. inherited Create;
  198. fType := cetObject;
  199. fEventO := aEvent;
  200. end;
  201. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  202. {$IFDEF UTL_NESTED_PROCVARS}
  203. constructor TutlCallbackComparer.Create(const aEvent: TCompareEventN);
  204. begin
  205. inherited Create;
  206. fType := cetNested;
  207. fEventN := aEvent;
  208. end;
  209. {$ENDIF}
  210. end.