bits.inc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 1999-2008 by the Free Pascal development team
  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. {****************************************************************************}
  11. {* TBits *}
  12. {****************************************************************************}
  13. Procedure BitsError (const Msg : string);
  14. begin
  15. Raise EBitsError.Create(Msg) at get_caller_addr(get_frame), get_caller_frame(get_frame);
  16. end;
  17. Procedure BitsErrorFmt (const Msg : string; const Args : array of const);
  18. begin
  19. Raise EBitsError.CreateFmt(Msg,args) at get_caller_addr(get_frame), get_caller_frame(get_frame);
  20. end;
  21. {Min function for Longint}
  22. Function liMin(X, Y: Longint): Longint;
  23. begin
  24. Result := X;
  25. if X > Y then Result := Y;
  26. end;
  27. procedure TBits.CheckBitIndex (Bit : longint;CurrentSize : Boolean);
  28. begin
  29. if (bit<0) or (CurrentSize and (Bit >= FBSize)) then
  30. BitsErrorFmt(SErrInvalidBitIndex,[bit]);
  31. if (bit>=MaxBitFlags) then
  32. BitsErrorFmt(SErrIndexTooLarge,[bit])
  33. end;
  34. { ************* functions to match TBits class ************* }
  35. procedure TBits.setSize(value: longint);
  36. var
  37. newSize, loop: LongInt;
  38. begin
  39. CheckBitIndex(value, false);
  40. if value <> 0 then
  41. newSize := (value shr BITSHIFT) + 1
  42. else
  43. newSize := 0;
  44. if newSize <> FSize then
  45. begin
  46. ReAllocMem(FBits, newSize * SizeOf(longint));
  47. if FBits <> nil then
  48. begin
  49. if newSize > FSize then
  50. for loop := FSize to newSize - 1 do
  51. FBits^[loop] := 0;
  52. end
  53. else if newSize > 0 then
  54. BitsError(SErrOutOfMemory); { isn't ReallocMem supposed to throw EOutOfMemory? }
  55. FSize := newSize;
  56. end;
  57. FBSize := value;
  58. end;
  59. procedure TBits.SetBit(bit : longint; value : Boolean);
  60. var
  61. n: Integer;
  62. begin
  63. grow(bit+1); { validates bit range and adjusts FBSize if necessary }
  64. n := bit shr BITSHIFT;
  65. if value then
  66. FBits^[n] := FBits^[n] or (longword(1) shl (bit and MASK))
  67. else
  68. FBits^[n] := FBits^[n] and not (longword(1) shl (bit and MASK));
  69. end;
  70. function TBits.OpenBit : longint;
  71. var
  72. loop : longint;
  73. loop2 : longint;
  74. begin
  75. result := -1; {should only occur if the whole array is set}
  76. { map 0 to -1, 1..32 to 0, etc }
  77. for loop := 0 to ((FBSize + MASK) shr BITSHIFT) - 1 do
  78. begin
  79. if FBits^[loop] <> $FFFFFFFF then
  80. begin
  81. for loop2 := 0 to MASK do
  82. begin
  83. if (FBits^[loop] and (longint(1) shl loop2)) = 0 then
  84. begin
  85. result := (loop shl BITSHIFT) + loop2;
  86. if result > FBSize then
  87. result := FBSize;
  88. Exit;
  89. end;
  90. end;
  91. end;
  92. end;
  93. if FSize < MaxBitRec then
  94. result := FSize * 32; {first bit of next record}
  95. end;
  96. { ******************** TBits ***************************** }
  97. constructor TBits.Create(theSize : longint = 0 );
  98. begin
  99. FSize := 0;
  100. FBSize := 0;
  101. FBits := nil;
  102. findIndex := -1;
  103. findState := True; { no reason just setting it to something }
  104. if TheSize > 0 then grow(theSize);
  105. end;
  106. destructor TBits.Destroy;
  107. begin
  108. if FBits <> nil then
  109. FreeMem(FBits, FSize * SizeOf(longint));
  110. FBits := nil;
  111. inherited Destroy;
  112. end;
  113. procedure TBits.grow(nbit: longint);
  114. begin
  115. if nbit > FBSize then
  116. SetSize(nbit);
  117. end;
  118. function TBits.getFSize : longint;
  119. begin
  120. result := FSize;
  121. end;
  122. procedure TBits.seton(bit : longint);
  123. begin
  124. SetBit(bit, True);
  125. end;
  126. procedure TBits.clear(bit : longint);
  127. begin
  128. SetBit(bit, False);
  129. end;
  130. procedure TBits.clearall;
  131. var
  132. loop : longint;
  133. begin
  134. for loop := 0 to FSize - 1 do
  135. FBits^[loop] := 0;
  136. { don't clear FBSize here, it will cause exceptions on subsequent reading bit values }
  137. { use 'Size := 0' to reset everything and deallocate storage }
  138. end;
  139. function TBits.get(bit : longint) : Boolean;
  140. var
  141. n : longint;
  142. begin
  143. CheckBitIndex(bit,true);
  144. result := False;
  145. n := bit shr BITSHIFT;
  146. if (n < FSize) then
  147. result := (FBits^[n] and (longint(1) shl (bit and MASK))) <> 0;
  148. end;
  149. procedure TBits.andbits(bitset : TBits);
  150. var
  151. n : longint;
  152. loop : longint;
  153. begin
  154. if FSize < bitset.getFSize then
  155. n := FSize - 1
  156. else
  157. n := bitset.getFSize - 1;
  158. for loop := 0 to n do
  159. FBits^[loop] := FBits^[loop] and bitset.FBits^[loop];
  160. for loop := n + 1 to FSize - 1 do
  161. FBits^[loop] := 0;
  162. end;
  163. procedure TBits.notbits(bitset : TBits);
  164. var
  165. n : longint;
  166. jj : cardinal;
  167. loop : longint;
  168. begin
  169. if FSize < bitset.getFSize then
  170. n := FSize - 1
  171. else
  172. n := bitset.getFSize - 1;
  173. for loop := 0 to n do
  174. begin
  175. jj := FBits^[loop];
  176. FBits^[loop] := FBits^[loop] and (jj xor bitset.FBits^[loop]);
  177. end;
  178. end;
  179. procedure TBits.orbits(bitset : TBits);
  180. var
  181. loop : longint;
  182. begin
  183. grow(bitset.Size);
  184. for loop := 0 to bitset.getFSize-1 do
  185. FBits^[loop] := FBits^[loop] or bitset.FBits^[loop];
  186. end;
  187. procedure TBits.xorbits(bitset : TBits);
  188. var
  189. loop : longint;
  190. begin
  191. grow(bitset.Size);
  192. for loop := 0 to bitset.getFSize-1 do
  193. FBits^[loop] := FBits^[loop] xor bitset.FBits^[loop];
  194. end;
  195. function TBits.Equals(Obj : TObject): Boolean;
  196. begin
  197. if Obj is TBits then
  198. Result := Equals(TBits(Obj))
  199. else
  200. Result := inherited Equals(Obj);
  201. end;
  202. function TBits.equals(bitset : TBits) : Boolean;
  203. var
  204. n : longint;
  205. loop : longint;
  206. begin
  207. result := False;
  208. if FSize < bitset.getFSize then
  209. n := FSize - 1
  210. else
  211. n := bitset.getFSize - 1;
  212. for loop := 0 to n do
  213. if FBits^[loop] <> bitset.FBits^[loop] then exit;
  214. if FSize - 1 > n then
  215. begin
  216. for loop := n to FSize - 1 do
  217. if FBits^[loop] <> 0 then exit;
  218. end
  219. else if bitset.getFSize - 1 > n then
  220. for loop := n to bitset.getFSize - 1 do
  221. if bitset.FBits^[loop] <> 0 then exit;
  222. result := True; {passed all tests}
  223. end;
  224. { us this in place of calling FindFirstBit. It sets the current }
  225. { index used by FindNextBit and FindPrevBit }
  226. procedure TBits.SetIndex(index : longint);
  227. begin
  228. CheckBitIndex(index,true);
  229. findIndex := index;
  230. end;
  231. { When state is set to True it looks for bits that are turned On (1) }
  232. { and when it is set to False it looks for bits that are turned }
  233. { off (0). }
  234. function TBits.FindFirstBit(state : boolean) : longint;
  235. var
  236. loop : longint;
  237. loop2 : longint;
  238. startIndex : longint;
  239. stopIndex : Longint;
  240. compareVal : cardinal;
  241. begin
  242. result := -1; {should only occur if none are set}
  243. findState := state;
  244. if state = False then
  245. compareVal := $FFFFFFFF { looking for off bits }
  246. else
  247. compareVal := $00000000; { looking for on bits }
  248. for loop := 0 to FSize - 1 do
  249. begin
  250. if FBits^[loop] <> compareVal then
  251. begin
  252. startIndex := loop * 32;
  253. stopIndex:= liMin(StartIndex+31,FBSize -1);
  254. for loop2 := startIndex to stopIndex do
  255. begin
  256. if get(loop2) = state then
  257. begin
  258. result := loop2;
  259. break; { use this as the index to return }
  260. end;
  261. end;
  262. break; {stop looking for bit in records }
  263. end;
  264. end;
  265. findIndex := result;
  266. end;
  267. function TBits.FindNextBit : longint;
  268. var
  269. loop : longint;
  270. begin
  271. result := -1; { will occur only if no other bits set to }
  272. { current findState }
  273. if findIndex > -1 then { must have called FindFirstBit first }
  274. begin { or set the start index }
  275. for loop := findIndex + 1 to FBSize-1 do
  276. begin
  277. if get(loop) = findState then
  278. begin
  279. result := loop;
  280. break;
  281. end;
  282. end;
  283. findIndex := result;
  284. end;
  285. end;
  286. function TBits.FindPrevBit : longint;
  287. var
  288. loop : longint;
  289. begin
  290. result := -1; { will occur only if no other bits set to }
  291. { current findState }
  292. if findIndex > -1 then { must have called FindFirstBit first }
  293. begin { or set the start index }
  294. for loop := findIndex - 1 downto 0 do
  295. begin
  296. if get(loop) = findState then
  297. begin
  298. result := loop;
  299. break;
  300. end;
  301. end;
  302. findIndex := result;
  303. end;
  304. end;