bits.inc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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. loop : longint;
  167. begin
  168. if FSize < bitset.getFSize then
  169. n := FSize - 1
  170. else
  171. n := bitset.getFSize - 1;
  172. for loop := 0 to n do
  173. FBits^[loop] := FBits^[loop] xor bitset.FBits^[loop];
  174. end;
  175. procedure TBits.orbits(bitset : TBits);
  176. var
  177. loop : longint;
  178. begin
  179. grow(bitset.Size);
  180. for loop := 0 to bitset.getFSize-1 do
  181. FBits^[loop] := FBits^[loop] or bitset.FBits^[loop];
  182. end;
  183. procedure TBits.xorbits(bitset : TBits);
  184. var
  185. loop : longint;
  186. begin
  187. grow(bitset.Size);
  188. for loop := 0 to bitset.getFSize-1 do
  189. FBits^[loop] := FBits^[loop] xor bitset.FBits^[loop];
  190. end;
  191. function TBits.Equals(Obj : TObject): Boolean;
  192. begin
  193. if Obj is TBits then
  194. Result := Equals(TBits(Obj))
  195. else
  196. Result := inherited Equals(Obj);
  197. end;
  198. function TBits.equals(bitset : TBits) : Boolean;
  199. var
  200. n : longint;
  201. loop : longint;
  202. begin
  203. result := False;
  204. if FSize < bitset.getFSize then
  205. n := FSize - 1
  206. else
  207. n := bitset.getFSize - 1;
  208. for loop := 0 to n do
  209. if FBits^[loop] <> bitset.FBits^[loop] then exit;
  210. if FSize - 1 > n then
  211. begin
  212. for loop := n to FSize - 1 do
  213. if FBits^[loop] <> 0 then exit;
  214. end
  215. else if bitset.getFSize - 1 > n then
  216. for loop := n to bitset.getFSize - 1 do
  217. if bitset.FBits^[loop] <> 0 then exit;
  218. result := True; {passed all tests}
  219. end;
  220. { us this in place of calling FindFirstBit. It sets the current }
  221. { index used by FindNextBit and FindPrevBit }
  222. procedure TBits.SetIndex(index : longint);
  223. begin
  224. CheckBitIndex(index,true);
  225. findIndex := index;
  226. end;
  227. { When state is set to True it looks for bits that are turned On (1) }
  228. { and when it is set to False it looks for bits that are turned }
  229. { off (0). }
  230. function TBits.FindFirstBit(state : boolean) : longint;
  231. var
  232. loop : longint;
  233. loop2 : longint;
  234. startIndex : longint;
  235. stopIndex : Longint;
  236. compareVal : cardinal;
  237. begin
  238. result := -1; {should only occur if none are set}
  239. findState := state;
  240. if state = False then
  241. compareVal := $FFFFFFFF { looking for off bits }
  242. else
  243. compareVal := $00000000; { looking for on bits }
  244. for loop := 0 to FSize - 1 do
  245. begin
  246. if FBits^[loop] <> compareVal then
  247. begin
  248. startIndex := loop * 32;
  249. stopIndex:= liMin(StartIndex+31,FBSize -1);
  250. for loop2 := startIndex to stopIndex do
  251. begin
  252. if get(loop2) = state then
  253. begin
  254. result := loop2;
  255. break; { use this as the index to return }
  256. end;
  257. end;
  258. break; {stop looking for bit in records }
  259. end;
  260. end;
  261. findIndex := result;
  262. end;
  263. function TBits.FindNextBit : longint;
  264. var
  265. loop : longint;
  266. begin
  267. result := -1; { will occur only if no other bits set to }
  268. { current findState }
  269. if findIndex > -1 then { must have called FindFirstBit first }
  270. begin { or set the start index }
  271. for loop := findIndex + 1 to FBSize-1 do
  272. begin
  273. if get(loop) = findState then
  274. begin
  275. result := loop;
  276. break;
  277. end;
  278. end;
  279. findIndex := result;
  280. end;
  281. end;
  282. function TBits.FindPrevBit : longint;
  283. var
  284. loop : longint;
  285. begin
  286. result := -1; { will occur only if no other bits set to }
  287. { current findState }
  288. if findIndex > -1 then { must have called FindFirstBit first }
  289. begin { or set the start index }
  290. for loop := findIndex - 1 downto 0 do
  291. begin
  292. if get(loop) = findState then
  293. begin
  294. result := loop;
  295. break;
  296. end;
  297. end;
  298. findIndex := result;
  299. end;
  300. end;