bits.inc 9.1 KB

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