2
0

bits.inc 8.6 KB

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