bits.inc 8.9 KB

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