ghashmap.pp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. {
  2. This file is part of the Free Pascal FCL library.
  3. BSD parts (c) 2011 Vlado Boza
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY;without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {$mode objfpc}
  11. unit ghashmap;
  12. interface
  13. uses gvector, gutil, garrayutils;
  14. const baseFDataSize = 8;
  15. {Thash should have one class function hash(a:TKey, n:longint):longint which return uniformly distributed
  16. value in range <0,n-1> base only on arguments, n will be always power of 2}
  17. type
  18. generic THashmapIterator<TKey, TValue, T, TTable>=class
  19. public
  20. type PValue=^TValue;
  21. var
  22. Fh,Fp:SizeUInt;
  23. FData:TTable;
  24. function Next:boolean;inline;
  25. function GetData:T;inline;
  26. function GetKey:TKey;inline;
  27. function GetValue:TValue;inline;
  28. function GetMutable:PValue;inline;
  29. procedure SetValue(value:TValue);inline;
  30. property Data:T read GetData;
  31. property Key:TKey read GetKey;
  32. property Value:TValue read GetValue write SetValue;
  33. property MutableValue:PValue read GetMutable;
  34. end;
  35. generic THashmap<TKey, TValue, Thash>=class
  36. public
  37. type
  38. TPair=record
  39. Value:TValue;
  40. Key:TKey;
  41. end;
  42. var
  43. private
  44. type
  45. TContainer = specialize TVector<TPair>;
  46. TTable = specialize TVector<TContainer>;
  47. var
  48. FData:TTable;
  49. FDataSize:SizeUInt;
  50. procedure EnlargeTable;
  51. public
  52. type
  53. TIterator = specialize THashmapIterator<TKey, TValue, TPair, TTable>;
  54. constructor create;
  55. destructor destroy;override;
  56. procedure insert(key:TKey;value:TValue);inline;
  57. function contains(key:TKey):boolean;inline;
  58. function size:SizeUInt;inline;
  59. procedure delete(key:TKey);inline;
  60. function IsEmpty:boolean;inline;
  61. function GetData(key:TKey):TValue;inline;
  62. property Items[i : TKey]: TValue read GetData write Insert; default;
  63. function Iterator:TIterator;
  64. end;
  65. implementation
  66. function THashmap.Size:SizeUInt;inline;
  67. begin
  68. Size:=FDataSize;
  69. end;
  70. destructor THashmap.Destroy;
  71. var i:SizeUInt;
  72. begin
  73. for i:=0 to FData.size-1 do
  74. (FData[i]).Destroy;
  75. FData.Destroy;
  76. end;
  77. function THashmap.IsEmpty():boolean;inline;
  78. begin
  79. if Size()=0 then
  80. IsEmpty:=true
  81. else
  82. IsEmpty:=false;
  83. end;
  84. procedure THashmap.EnlargeTable;
  85. var i,j,h,oldDataSize:SizeUInt;
  86. value:TPair;
  87. begin
  88. oldDataSize:=FData.size;
  89. FData.resize(FData.size*2);
  90. for i:=oldDataSize to FData.size-1 do
  91. FData[i] := TContainer.create;
  92. for i:=oldDataSize-1 downto 0 do begin
  93. j := 0;
  94. while j < (FData[i]).size do begin
  95. value := (FData[i])[j];
  96. h:=Thash.hash(value.key,FData.size);
  97. if (h <> i) then begin
  98. (FData[i])[j] := (FData[i]).back;
  99. (FData[i]).popback;
  100. (FData[h]).pushback(value);
  101. end else
  102. inc(j);
  103. end;
  104. end;
  105. end;
  106. constructor THashmap.create;
  107. var i:longint;
  108. begin
  109. FDataSize:=0;
  110. FData:=TTable.create;
  111. FData.resize(baseFDataSize);
  112. for i:=0 to baseFDataSize-1 do
  113. FData[i]:=TContainer.create;
  114. end;
  115. function THashmap.contains(key:TKey):boolean;inline;
  116. var i,h,bs:longint;
  117. begin
  118. h:=Thash.hash(key,FData.size);
  119. bs:=(FData[h]).size;
  120. for i:=0 to bs-1 do begin
  121. if (((FData[h])[i]).Key=key) then exit(true);
  122. end;
  123. exit(false);
  124. end;
  125. function THashmap.GetData(key:TKey):TValue;inline;
  126. var i,h,bs:longint;
  127. begin
  128. h:=Thash.hash(key,FData.size);
  129. bs:=(FData[h]).size;
  130. for i:=0 to bs-1 do begin
  131. if (((FData[h])[i]).Key=key) then exit(((FData[h])[i]).Value);
  132. end;
  133. end;
  134. procedure THashmap.insert(key:TKey;value:TValue);inline;
  135. var pair:TPair; i,h,bs:longint;
  136. begin
  137. h:=Thash.hash(key,FData.size);
  138. bs:=(FData[h]).size;
  139. for i:=0 to bs-1 do begin
  140. if (((FData[h])[i]).Key=key) then begin
  141. ((FData[h]).mutable[i])^.value := value;
  142. exit;
  143. end;
  144. end;
  145. pair.Key := key;
  146. pair.Value := value;
  147. inc(FDataSize);
  148. (FData[h]).pushback(pair);
  149. if (FDataSize > 5*FData.size) then
  150. EnlargeTable;
  151. end;
  152. procedure THashmap.delete(key:TKey);inline;
  153. var h,i:SizeUInt;
  154. begin
  155. h:=Thash.hash(key,FData.size);
  156. i:=0;
  157. while i < (FData[h]).size do begin
  158. if (((FData[h])[i]).key=key) then begin
  159. (FData[h])[i] := (FData[h]).back;
  160. (FData[h]).popback;
  161. dec(FDataSize);
  162. exit;
  163. end;
  164. inc(i);
  165. end;
  166. end;
  167. function THashmapIterator.Next:boolean;
  168. begin
  169. inc(Fp);
  170. if (Fp = (FData[Fh]).size) then begin
  171. Fp:=0; inc(Fh);
  172. while Fh < FData.size do begin
  173. if ((FData[Fh]).size > 0) then break;
  174. inc(Fh);
  175. end;
  176. if (Fh = FData.size) then exit(false);
  177. end;
  178. Next := true;
  179. end;
  180. function THashmapIterator.GetData:T;
  181. begin
  182. GetData:=(FData[Fh])[Fp];
  183. end;
  184. function THashmap.Iterator:TIterator;
  185. var h,p:SizeUInt;
  186. begin
  187. h:=0;
  188. p:=0;
  189. while h < FData.size do begin
  190. if ((FData[h]).size > 0) then break;
  191. inc(h);
  192. end;
  193. if (h = FData.size) then exit(nil);
  194. Iterator := TIterator.create;
  195. Iterator.Fh := h;
  196. Iterator.Fp := p;
  197. Iterator.FData := FData;
  198. end;
  199. function THashmapIterator.GetKey:TKey;inline;
  200. begin
  201. GetKey:=((FData[Fh])[Fp]).Key;
  202. end;
  203. function THashmapIterator.GetValue:TValue;inline;
  204. begin
  205. GetValue:=((FData[Fh])[Fp]).Value;
  206. end;
  207. function THashmapIterator.GetMutable:PValue;inline;
  208. begin
  209. GetMutable:=@((FData[Fh]).Mutable[Fp]^.Value);
  210. end;
  211. procedure THashmapIterator.SetValue(value:TValue);inline;
  212. begin
  213. ((FData[Fh]).mutable[Fp])^.Value := value;
  214. end;
  215. end.