bits.inc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  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 (Msg : string);
  14. begin
  15. Raise EBitsError.Create(Msg) at get_caller_addr(get_frame);
  16. end;
  17. Procedure BitsErrorFmt (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. procedure TBits.Resize(Nbit: longint);
  35. var
  36. newSize : longint;
  37. loop : longint;
  38. begin
  39. CheckBitindex(nbit,false);
  40. newSize := (nbit shr BITSHIFT) + 1;
  41. if newSize <> FSize then
  42. begin
  43. ReAllocMem(FBits, newSize * SizeOf(longint));
  44. if FBits <> nil then
  45. begin
  46. if newSize > FSize then
  47. for loop := FSize to newSize - 1 do
  48. FBits^[loop] := 0;
  49. FSize := newSize;
  50. FBSize := nbit + 1;
  51. end
  52. else
  53. BitsError(SErrOutOfMemory);
  54. end;
  55. end;
  56. { ************* functions to match TBits class ************* }
  57. function TBits.getSize : longint;
  58. begin
  59. result := FBSize;
  60. end;
  61. procedure TBits.setSize(value : longint);
  62. begin
  63. if value=0 then
  64. resize(0) // truncate
  65. else
  66. Resize(value - 1);
  67. FBSize:= value;
  68. end;
  69. procedure TBits.SetBit(bit : longint; value : Boolean);
  70. begin
  71. if value = True then
  72. seton(bit)
  73. else
  74. clear(bit);
  75. end;
  76. function TBits.OpenBit : longint;
  77. var
  78. loop : longint;
  79. loop2 : longint;
  80. startIndex : longint;
  81. stopIndex : Longint;
  82. begin
  83. result := -1; {should only occur if the whole array is set}
  84. for loop := 0 to FSize - 1 do
  85. begin
  86. if FBits^[loop] <> $FFFFFFFF then
  87. begin
  88. startIndex := loop * 32;
  89. stopIndex := liMin ( FBSize -1,startIndex + 31) ;
  90. for loop2 := startIndex to stopIndex do
  91. begin
  92. if get(loop2) = False then
  93. begin
  94. result := loop2;
  95. break; { use this as the index to return }
  96. end;
  97. end;
  98. if result = -1 then begin
  99. result := FBSize;
  100. inc(FBSize);
  101. end;
  102. break; {stop looking for empty bit in records }
  103. end;
  104. end;
  105. if result = -1 then
  106. if FSize < MaxBitRec then
  107. result := FSize * 32; {first bit of next record}
  108. end;
  109. { ******************** TBits ***************************** }
  110. constructor TBits.Create(theSize : longint = 0 );
  111. begin
  112. FSize := 0;
  113. FBSize := 0;
  114. FBits := nil;
  115. findIndex := -1;
  116. findState := True; { no reason just setting it to something }
  117. if TheSize > 0 then grow(theSize-1);
  118. end;
  119. destructor TBits.Destroy;
  120. begin
  121. if FBits <> nil then
  122. FreeMem(FBits, FSize * SizeOf(longint));
  123. FBits := nil;
  124. inherited Destroy;
  125. end;
  126. procedure TBits.grow(nbit : longint);
  127. var
  128. newSize : longint;
  129. begin
  130. newSize := (nbit shr BITSHIFT) + 1;
  131. if newSize > FSize then Resize(nbit);
  132. end;
  133. function TBits.getFSize : longint;
  134. begin
  135. result := FSize;
  136. end;
  137. procedure TBits.seton(bit : longint);
  138. var
  139. n : longint;
  140. begin
  141. n := bit shr BITSHIFT;
  142. grow(bit);
  143. FBits^[n] := FBits^[n] or (cardinal(1) shl (bit and MASK));
  144. if bit >= FBSize then FBSize := bit;
  145. end;
  146. procedure TBits.clear(bit : longint);
  147. var
  148. n : longint;
  149. begin
  150. CheckBitIndex(bit,false);
  151. n := bit shr BITSHIFT;
  152. grow(bit);
  153. FBits^[n] := FBits^[n] and not(longint(1) shl (bit and MASK));
  154. if bit >= FBSize then FBSize := bit + 1;
  155. end;
  156. procedure TBits.clearall;
  157. var
  158. loop : longint;
  159. begin
  160. for loop := 0 to FSize - 1 do
  161. FBits^[loop] := 0;
  162. {Should FBSize be cleared too? - I think so}
  163. FBSize := 0;
  164. end;
  165. function TBits.get(bit : longint) : Boolean;
  166. var
  167. n : longint;
  168. begin
  169. CheckBitIndex(bit,true);
  170. result := False;
  171. n := bit shr BITSHIFT;
  172. if (n < FSize) then
  173. result := (FBits^[n] and (longint(1) shl (bit and MASK))) <> 0;
  174. end;
  175. procedure TBits.andbits(bitset : TBits);
  176. var
  177. n : longint;
  178. loop : longint;
  179. begin
  180. if FSize < bitset.getFSize then
  181. n := FSize - 1
  182. else
  183. n := bitset.getFSize - 1;
  184. for loop := 0 to n do
  185. FBits^[loop] := FBits^[loop] and bitset.FBits^[loop];
  186. for loop := n + 1 to FSize - 1 do
  187. FBits^[loop] := 0;
  188. end;
  189. procedure TBits.notbits(bitset : TBits);
  190. var
  191. n : longint;
  192. jj : cardinal;
  193. loop : longint;
  194. begin
  195. if FSize < bitset.getFSize then
  196. n := FSize - 1
  197. else
  198. n := bitset.getFSize - 1;
  199. for loop := 0 to n do
  200. begin
  201. jj := FBits^[loop];
  202. FBits^[loop] := FBits^[loop] and (jj xor bitset.FBits^[loop]);
  203. end;
  204. end;
  205. procedure TBits.orbits(bitset : TBits);
  206. var
  207. n : longint;
  208. loop : longint;
  209. begin
  210. if FSize < bitset.getFSize then
  211. n := bitset.getFSize - 1
  212. else
  213. n := FSize - 1;
  214. grow(n shl BITSHIFT);
  215. for loop := 0 to n do
  216. FBits^[loop] := FBits^[loop] or bitset.FBits^[loop];
  217. end;
  218. procedure TBits.xorbits(bitset : TBits);
  219. var
  220. n : longint;
  221. loop : longint;
  222. begin
  223. if FSize < bitset.getFSize then
  224. n := bitset.getFSize - 1
  225. else
  226. n := FSize - 1;
  227. grow(n shl BITSHIFT);
  228. for loop := 0 to n do
  229. FBits^[loop] := FBits^[loop] xor bitset.FBits^[loop];
  230. end;
  231. function TBits.equals(bitset : TBits) : Boolean;
  232. var
  233. n : longint;
  234. loop : longint;
  235. begin
  236. result := False;
  237. if FSize < bitset.getFSize then
  238. n := FSize - 1
  239. else
  240. n := bitset.getFSize - 1;
  241. for loop := 0 to n do
  242. if FBits^[loop] <> bitset.FBits^[loop] then exit;
  243. if FSize - 1 > n then
  244. begin
  245. for loop := n to FSize - 1 do
  246. if FBits^[loop] <> 0 then exit;
  247. end
  248. else if bitset.getFSize - 1 > n then
  249. for loop := n to bitset.getFSize - 1 do
  250. if bitset.FBits^[loop] <> 0 then exit;
  251. result := True; {passed all tests}
  252. end;
  253. { us this in place of calling FindFirstBit. It sets the current }
  254. { index used by FindNextBit and FindPrevBit }
  255. procedure TBits.SetIndex(index : longint);
  256. begin
  257. CheckBitIndex(index,true);
  258. findIndex := index;
  259. end;
  260. { When state is set to True it looks for bits that are turned On (1) }
  261. { and when it is set to False it looks for bits that are turned }
  262. { off (0). }
  263. function TBits.FindFirstBit(state : boolean) : longint;
  264. var
  265. loop : longint;
  266. loop2 : longint;
  267. startIndex : longint;
  268. stopIndex : Longint;
  269. compareVal : cardinal;
  270. begin
  271. result := -1; {should only occur if none are set}
  272. findState := state;
  273. if state = False then
  274. compareVal := $FFFFFFFF { looking for off bits }
  275. else
  276. compareVal := $00000000; { looking for on bits }
  277. for loop := 0 to FSize - 1 do
  278. begin
  279. if FBits^[loop] <> compareVal then
  280. begin
  281. startIndex := loop * 32;
  282. stopIndex:= liMin(StartIndex+31,FBSize -1);
  283. for loop2 := startIndex to stopIndex do
  284. begin
  285. if get(loop2) = state then
  286. begin
  287. result := loop2;
  288. break; { use this as the index to return }
  289. end;
  290. end;
  291. break; {stop looking for bit in records }
  292. end;
  293. end;
  294. findIndex := result;
  295. end;
  296. function TBits.FindNextBit : longint;
  297. var
  298. loop : longint;
  299. maxVal : longint;
  300. begin
  301. result := -1; { will occur only if no other bits set to }
  302. { current findState }
  303. if findIndex > -1 then { must have called FindFirstBit first }
  304. begin { or set the start index }
  305. maxVal := (FSize * 32) - 1;
  306. for loop := findIndex + 1 to maxVal do
  307. begin
  308. if get(loop) = findState then
  309. begin
  310. result := loop;
  311. break;
  312. end;
  313. end;
  314. findIndex := result;
  315. end;
  316. end;
  317. function TBits.FindPrevBit : longint;
  318. var
  319. loop : longint;
  320. begin
  321. result := -1; { will occur only if no other bits set to }
  322. { current findState }
  323. if findIndex > -1 then { must have called FindFirstBit first }
  324. begin { or set the start index }
  325. for loop := findIndex - 1 downto 0 do
  326. begin
  327. if get(loop) = findState then
  328. begin
  329. result := loop;
  330. break;
  331. end;
  332. end;
  333. findIndex := result;
  334. end;
  335. end;