bits.inc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. {
  2. $Id: bits.inc,v 1.4 2005/02/14 17:13:31 peter Exp $
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************}
  12. {* TBits *}
  13. {****************************************************************************}
  14. Procedure BitsError (Msg : string);
  15. begin
  16. Raise EBitsError.Create(Msg) at get_caller_addr(get_frame);
  17. end;
  18. Procedure BitsErrorFmt (Msg : string; const Args : array of const);
  19. begin
  20. Raise EBitsError.CreateFmt(Msg,args) at get_caller_addr(get_frame);
  21. end;
  22. procedure TBits.CheckBitIndex (Bit : longint;CurrentSize : Boolean);
  23. begin
  24. if (bit<0) or (CurrentSize and (Bit>Size)) then
  25. BitsErrorFmt(SErrInvalidBitIndex,[bit]);
  26. if (bit>=MaxBitFlags) then
  27. BitsErrorFmt(SErrIndexTooLarge,[bit])
  28. end;
  29. { ************* functions to match TBits class ************* }
  30. function TBits.getSize : longint;
  31. begin
  32. result := (FSize shl BITSHIFT) - 1;
  33. end;
  34. procedure TBits.setSize(value : longint);
  35. begin
  36. grow(value - 1);
  37. end;
  38. procedure TBits.SetBit(bit : longint; value : Boolean);
  39. begin
  40. if value = True then
  41. seton(bit)
  42. else
  43. clear(bit);
  44. end;
  45. function TBits.OpenBit : longint;
  46. var
  47. loop : longint;
  48. loop2 : longint;
  49. startIndex : longint;
  50. begin
  51. result := -1; {should only occur if the whole array is set}
  52. for loop := 0 to FSize - 1 do
  53. begin
  54. if FBits^[loop] <> $FFFFFFFF then
  55. begin
  56. startIndex := loop * 32;
  57. for loop2 := startIndex to startIndex + 31 do
  58. begin
  59. if get(loop2) = False then
  60. begin
  61. result := loop2;
  62. break; { use this as the index to return }
  63. end;
  64. end;
  65. break; {stop looking for empty bit in records }
  66. end;
  67. end;
  68. if result = -1 then
  69. if FSize < MaxBitRec then
  70. result := FSize * 32; {first bit of next record}
  71. end;
  72. { ******************** TBits ***************************** }
  73. constructor TBits.Create(theSize : longint = 0 );
  74. begin
  75. FSize := 0;
  76. FBits := nil;
  77. findIndex := -1;
  78. findState := True; { no reason just setting it to something }
  79. grow(theSize);
  80. end;
  81. destructor TBits.Destroy;
  82. begin
  83. if FBits <> nil then
  84. FreeMem(FBits, FSize * SizeOf(longint));
  85. FBits := nil;
  86. inherited Destroy;
  87. end;
  88. procedure TBits.grow(nbit : longint);
  89. var
  90. newSize : longint;
  91. loop : longint;
  92. begin
  93. CheckBitindex(nbit,false);
  94. newSize := (nbit shr BITSHIFT) + 1;
  95. if newSize > FSize then
  96. begin
  97. ReAllocMem(FBits, newSize * SizeOf(longint));
  98. if FBits <> nil then
  99. begin
  100. if newSize > FSize then
  101. for loop := FSize to newSize - 1 do
  102. FBits^[loop] := 0;
  103. FSize := newSize;
  104. end
  105. else
  106. BitsError(SErrOutOfMemory);
  107. end;
  108. end;
  109. function TBits.getFSize : longint;
  110. begin
  111. result := FSize;
  112. end;
  113. procedure TBits.seton(bit : longint);
  114. var
  115. n : longint;
  116. begin
  117. n := bit shr BITSHIFT;
  118. grow(bit);
  119. FBits^[n] := FBits^[n] or (longint(1) shl (bit and MASK));
  120. end;
  121. procedure TBits.clear(bit : longint);
  122. var
  123. n : longint;
  124. begin
  125. CheckBitIndex(bit,false);
  126. n := bit shr BITSHIFT;
  127. grow(bit);
  128. FBits^[n] := FBits^[n] and not(longint(1) shl (bit and MASK));
  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. end;
  137. function TBits.get(bit : longint) : Boolean;
  138. var
  139. n : longint;
  140. begin
  141. CheckBitIndex(bit,true);
  142. result := False;
  143. n := bit shr BITSHIFT;
  144. if (n < FSize) then
  145. result := (FBits^[n] and (longint(1) shl (bit and MASK))) <> 0;
  146. end;
  147. procedure TBits.andbits(bitset : TBits);
  148. var
  149. n : longint;
  150. loop : longint;
  151. begin
  152. if FSize < bitset.getFSize then
  153. n := FSize - 1
  154. else
  155. n := bitset.getFSize - 1;
  156. for loop := 0 to n do
  157. FBits^[loop] := FBits^[loop] and bitset.FBits^[loop];
  158. for loop := n + 1 to FSize - 1 do
  159. FBits^[loop] := 0;
  160. end;
  161. procedure TBits.notbits(bitset : TBits);
  162. var
  163. n : longint;
  164. jj : longint;
  165. loop : longint;
  166. begin
  167. if FSize < bitset.getFSize then
  168. n := FSize - 1
  169. else
  170. n := bitset.getFSize - 1;
  171. for loop := 0 to n do
  172. begin
  173. jj := FBits^[loop];
  174. FBits^[loop] := FBits^[loop] and (jj xor bitset.FBits^[loop]);
  175. end;
  176. end;
  177. procedure TBits.orbits(bitset : TBits);
  178. var
  179. n : longint;
  180. loop : longint;
  181. begin
  182. if FSize < bitset.getFSize then
  183. n := bitset.getFSize - 1
  184. else
  185. n := FSize - 1;
  186. grow(n shl BITSHIFT);
  187. for loop := 0 to n do
  188. FBits^[loop] := FBits^[loop] or bitset.FBits^[loop];
  189. end;
  190. procedure TBits.xorbits(bitset : TBits);
  191. var
  192. n : longint;
  193. loop : longint;
  194. begin
  195. if FSize < bitset.getFSize then
  196. n := bitset.getFSize - 1
  197. else
  198. n := FSize - 1;
  199. grow(n shl BITSHIFT);
  200. for loop := 0 to n do
  201. FBits^[loop] := FBits^[loop] xor bitset.FBits^[loop];
  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. findIndex := index;
  230. end;
  231. { When state is set to True it looks for bits that are turned On (1) }
  232. { and when it is set to False it looks for bits that are turned }
  233. { off (0). }
  234. function TBits.FindFirstBit(state : boolean) : longint;
  235. var
  236. loop : longint;
  237. loop2 : longint;
  238. startIndex : longint;
  239. compareVal : cardinal;
  240. begin
  241. result := -1; {should only occur if none are set}
  242. findState := state;
  243. if state = False then
  244. compareVal := $FFFFFFFF { looking for off bits }
  245. else
  246. compareVal := $00000000; { looking for on bits }
  247. for loop := 0 to FSize - 1 do
  248. begin
  249. if FBits^[loop] <> compareVal then
  250. begin
  251. startIndex := loop * 32;
  252. for loop2 := startIndex to startIndex + 31 do
  253. begin
  254. if get(loop2) = state then
  255. begin
  256. result := loop2;
  257. break; { use this as the index to return }
  258. end;
  259. end;
  260. break; {stop looking for bit in records }
  261. end;
  262. end;
  263. findIndex := result;
  264. end;
  265. function TBits.FindNextBit : longint;
  266. var
  267. loop : longint;
  268. maxVal : longint;
  269. begin
  270. result := -1; { will occur only if no other bits set to }
  271. { current findState }
  272. if findIndex > -1 then { must have called FindFirstBit first }
  273. begin { or set the start index }
  274. maxVal := (FSize * 32) - 1;
  275. for loop := findIndex + 1 to maxVal do
  276. begin
  277. if get(loop) = findState then
  278. begin
  279. result := loop;
  280. break;
  281. end;
  282. end;
  283. findIndex := result;
  284. end;
  285. end;
  286. function TBits.FindPrevBit : longint;
  287. var
  288. loop : longint;
  289. begin
  290. result := -1; { will occur only if no other bits set to }
  291. { current findState }
  292. if findIndex > -1 then { must have called FindFirstBit first }
  293. begin { or set the start index }
  294. for loop := findIndex - 1 downto 0 do
  295. begin
  296. if get(loop) = findState then
  297. begin
  298. result := loop;
  299. break;
  300. end;
  301. end;
  302. findIndex := result;
  303. end;
  304. end;
  305. {
  306. $Log: bits.inc,v $
  307. Revision 1.4 2005/02/14 17:13:31 peter
  308. * truncate log
  309. }