bits.inc 8.6 KB

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