bits.inc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1998 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. { ************* functions to match TBits class ************* }
  15. function TBits.getSize : longint;
  16. begin
  17. result := (FSize shl BITSHIFT) - 1;
  18. end;
  19. procedure TBits.setSize(value : longint);
  20. begin
  21. grow(value - 1);
  22. end;
  23. procedure TBits.SetBit(bit : longint; value : Boolean);
  24. begin
  25. if value = True then
  26. seton(bit)
  27. else
  28. clear(bit);
  29. end;
  30. function TBits.OpenBit : longint;
  31. var
  32. loop : longint;
  33. loop2 : longint;
  34. startIndex : longint;
  35. begin
  36. result := -1; {should only occur if the whole array is set}
  37. for loop := 0 to FSize - 1 do
  38. begin
  39. if FBits^[loop] <> $FFFFFFFF then
  40. begin
  41. startIndex := loop * 32;
  42. for loop2 := startIndex to startIndex + 31 do
  43. begin
  44. if get(loop2) = False then
  45. begin
  46. result := loop2;
  47. break; { use this as the index to return }
  48. end;
  49. end;
  50. break; {stop looking for empty bit in records }
  51. end;
  52. end;
  53. if result = -1 then
  54. if FSize < MaxBitRec then
  55. result := FSize * 32; {first bit of next record}
  56. end;
  57. { ******************** TBits ***************************** }
  58. constructor TBits.Create(theSize : longint);
  59. begin
  60. FSize := 0;
  61. FBits := nil;
  62. findIndex := -1;
  63. findState := True; { no reason just setting it to something }
  64. grow(theSize);
  65. end;
  66. destructor TBits.Destroy;
  67. begin
  68. if FBits <> nil then
  69. FreeMem(FBits, FSize * SizeOf(longint));
  70. FBits := nil;
  71. inherited Destroy;
  72. end;
  73. procedure TBits.grow(nbit : longint);
  74. var
  75. newSize : longint;
  76. loop : longint;
  77. begin
  78. if nbit >= MaxBitFlags then
  79. Raise EBitsError.Create('Bit index exceeds array limit');
  80. newSize := (nbit shr BITSHIFT) + 1;
  81. if newSize > FSize then
  82. begin
  83. {$IFDEF VER80}
  84. if FBits = nil then
  85. FBits := AllocMem(newSize * SizeOf(longint))
  86. else
  87. FBits := ReAllocMem(bits, currentSize * SizeOf(longint), newSize * SizeOf(longint));
  88. {$ELSE}
  89. {$IFDEF FPC}
  90. if FBits = nil then
  91. FBits := AllocMem(newSize * SizeOf(longint))
  92. else
  93. ReAllocMem(FBits, FSize * SizeOf(longint), newSize * SizeOf(longint));
  94. {$ELSE}
  95. { Delphi 2 & 3 keep track of the current size for you }
  96. ReAllocMem(FBits, newSize * SizeOf(longint));
  97. {$ENDIF}
  98. {$ENDIF}
  99. if FBits <> nil then
  100. begin
  101. if newSize > FSize then
  102. for loop := FSize to newSize - 1 do
  103. FBits^[loop] := 0;
  104. FSize := newSize;
  105. end;
  106. end;
  107. end;
  108. function TBits.getFSize : longint;
  109. begin
  110. result := FSize;
  111. end;
  112. procedure TBits.seton(bit : longint);
  113. var
  114. n : longint;
  115. begin
  116. n := bit shr BITSHIFT;
  117. grow(bit);
  118. FBits^[n] := FBits^[n] or (longint(1) shl (bit and MASK));
  119. end;
  120. procedure TBits.clear(bit : longint);
  121. var
  122. n : longint;
  123. begin
  124. n := bit shr BITSHIFT;
  125. grow(bit);
  126. FBits^[n] := FBits^[n] and not(longint(1) shl (bit and MASK));
  127. end;
  128. procedure TBits.clearall;
  129. var
  130. loop : longint;
  131. begin
  132. for loop := 0 to FSize - 1 do
  133. FBits^[loop] := 0;
  134. end;
  135. function TBits.get(bit : longint) : Boolean;
  136. var
  137. n : longint;
  138. begin
  139. result := False;
  140. if bit >= MaxBitFlags then
  141. Raise EBitsError.Create('Bit index exceeds array limit');
  142. n := bit shr BITSHIFT;
  143. if (n < FSize) then
  144. result := (FBits^[n] and (longint(1) shl (bit and MASK))) <> 0;
  145. end;
  146. procedure TBits.andbits(bitset : TBits);
  147. var
  148. n : longint;
  149. loop : longint;
  150. begin
  151. if FSize < bitset.getFSize then
  152. n := FSize - 1
  153. else
  154. n := bitset.getFSize - 1;
  155. for loop := 0 to n do
  156. FBits^[loop] := FBits^[loop] and bitset.FBits^[loop];
  157. for loop := n + 1 to FSize - 1 do
  158. FBits^[loop] := 0;
  159. end;
  160. procedure TBits.notbits(bitset : TBits);
  161. var
  162. n : longint;
  163. jj : longint;
  164. loop : longint;
  165. begin
  166. if FSize < bitset.getFSize then
  167. n := FSize - 1
  168. else
  169. n := bitset.getFSize - 1;
  170. for loop := 0 to n do
  171. begin
  172. jj := FBits^[loop];
  173. FBits^[loop] := FBits^[loop] and (jj xor bitset.FBits^[loop]);
  174. end;
  175. end;
  176. procedure TBits.orbits(bitset : TBits);
  177. var
  178. n : longint;
  179. loop : longint;
  180. begin
  181. if FSize < bitset.getFSize then
  182. n := bitset.getFSize - 1
  183. else
  184. n := FSize - 1;
  185. grow(n shl BITSHIFT);
  186. for loop := 0 to n do
  187. FBits^[loop] := FBits^[loop] or bitset.FBits^[loop];
  188. end;
  189. procedure TBits.xorbits(bitset : TBits);
  190. var
  191. n : longint;
  192. loop : longint;
  193. begin
  194. if FSize < bitset.getFSize then
  195. n := bitset.getFSize - 1
  196. else
  197. n := FSize - 1;
  198. grow(n shl BITSHIFT);
  199. for loop := 0 to n do
  200. FBits^[loop] := FBits^[loop] xor bitset.FBits^[loop];
  201. end;
  202. function TBits.equals(bitset : TBits) : Boolean;
  203. var
  204. n : longint;
  205. loop : longint;
  206. begin
  207. result := False;
  208. if FSize < bitset.getFSize then
  209. n := FSize - 1
  210. else
  211. n := bitset.getFSize - 1;
  212. for loop := 0 to n do
  213. if FBits^[loop] <> bitset.FBits^[loop] then exit;
  214. if FSize - 1 > n then
  215. begin
  216. for loop := n to FSize - 1 do
  217. if FBits^[loop] <> 0 then exit;
  218. end
  219. else if bitset.getFSize - 1 > n then
  220. for loop := n to bitset.getFSize - 1 do
  221. if bitset.FBits^[loop] <> 0 then exit;
  222. result := True; {passed all tests}
  223. end;
  224. { us this in place of calling FindFirstBit. It sets the current }
  225. { index used by FindNextBit and FindPrevBit }
  226. procedure TBits.SetIndex(index : longint);
  227. begin
  228. findIndex := index;
  229. end;
  230. { When state is set to True it looks for bits that are turned On (1) }
  231. { and when it is set to False it looks for bits that are turned }
  232. { off (0). }
  233. function TBits.FindFirstBit(state : boolean) : longint;
  234. var
  235. loop : longint;
  236. loop2 : longint;
  237. startIndex : longint;
  238. compareVal : longint;
  239. begin
  240. result := -1; {should only occur if none are set}
  241. findState := state;
  242. if state = False then
  243. compareVal := $FFFFFFFF { looking for off bits }
  244. else
  245. compareVal := $00000000; { looking for on bits }
  246. for loop := 0 to FSize - 1 do
  247. begin
  248. if FBits^[loop] <> compareVal then
  249. begin
  250. startIndex := loop * 32;
  251. for loop2 := startIndex to startIndex + 31 do
  252. begin
  253. if get(loop2) = state then
  254. begin
  255. result := loop2;
  256. break; { use this as the index to return }
  257. end;
  258. end;
  259. break; {stop looking for bit in records }
  260. end;
  261. end;
  262. findIndex := result;
  263. end;
  264. function TBits.FindNextBit : longint;
  265. var
  266. loop : longint;
  267. maxVal : longint;
  268. begin
  269. result := -1; { will occur only if no other bits set to }
  270. { current findState }
  271. if findIndex > -1 then { must have called FindFirstBit first }
  272. begin { or set the start index }
  273. maxVal := (FSize * 32) - 1;
  274. for loop := findIndex + 1 to maxVal do
  275. begin
  276. if get(loop) = findState then
  277. begin
  278. result := loop;
  279. break;
  280. end;
  281. end;
  282. findIndex := result;
  283. end;
  284. end;
  285. function TBits.FindPrevBit : longint;
  286. var
  287. loop : longint;
  288. begin
  289. result := -1; { will occur only if no other bits set to }
  290. { current findState }
  291. if findIndex > -1 then { must have called FindFirstBit first }
  292. begin { or set the start index }
  293. for loop := findIndex - 1 downto 0 do
  294. begin
  295. if get(loop) = findState then
  296. begin
  297. result := loop;
  298. break;
  299. end;
  300. end;
  301. findIndex := result;
  302. end;
  303. end;
  304. {
  305. $Log$
  306. Revision 1.4 1999-04-09 12:13:31 michael
  307. + Changed TBits to TbitsPlus from Michael A. Hess (renamed to Tbits)
  308. Revision 1.3 1998/11/04 14:36:29 michael
  309. Error handling always with exceptions
  310. Revision 1.2 1998/11/04 10:46:42 peter
  311. * exceptions work
  312. Revision 1.1 1998/05/04 14:30:11 michael
  313. * Split file according to Class; implemented dummys for all methods, so unit compiles.
  314. }