bits.inc 9.0 KB

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