bits.inc 8.4 KB

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