File indexing completed on 2025-01-05 04:37:29

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #ifndef BTBITSET_H
0007 #define BTBITSET_H
0008 
0009 #include "constants.h"
0010 #include <ktorrent_export.h>
0011 
0012 namespace bt
0013 {
0014 /**
0015  * @author Joris Guisson
0016  * @brief Simple implementation of a BitSet
0017  *
0018  * Simple implementation of a BitSet, can only turn on and off bits.
0019  * BitSet's are used to indicate which chunks we have or not.
0020  */
0021 class KTORRENT_EXPORT BitSet
0022 {
0023     Uint32 num_bits, num_bytes;
0024     Uint8 *data;
0025     Uint32 num_on;
0026 
0027 public:
0028     /**
0029      * Constructor.
0030      * @param num_bits The number of bits
0031      */
0032     BitSet(Uint32 num_bits = 8);
0033 
0034     /**
0035      * Manually set data.
0036      * @param data The data
0037      * @param num_bits The number of bits
0038      */
0039     BitSet(const Uint8 *data, Uint32 num_bits);
0040 
0041     /**
0042      * Copy constructor.
0043      * @param bs BitSet to copy
0044      * @return
0045      */
0046     BitSet(const BitSet &bs);
0047     virtual ~BitSet();
0048 
0049     /// See if the BitSet is null
0050     bool isNull() const
0051     {
0052         return num_bits == 0;
0053     }
0054 
0055     /**
0056      * Get the value of a bit, false means 0, true 1.
0057      * @param i Index of Bit
0058      */
0059     bool get(Uint32 i) const;
0060 
0061     /**
0062      * Set the value of a bit, false means 0, true 1.
0063      * @param i Index of Bit
0064      * @param on False means 0, true 1
0065      */
0066     void set(Uint32 i, bool on);
0067 
0068     /// Set all bits on or off
0069     void setAll(bool on);
0070 
0071     Uint32 getNumBytes() const
0072     {
0073         return num_bytes;
0074     }
0075     Uint32 getNumBits() const
0076     {
0077         return num_bits;
0078     }
0079     const Uint8 *getData() const
0080     {
0081         return data;
0082     }
0083     Uint8 *getData()
0084     {
0085         return data;
0086     }
0087 
0088     /// Get the number of on bits
0089     Uint32 numOnBits() const
0090     {
0091         return num_on;
0092     }
0093 
0094     /**
0095      * Set all bits to 0
0096      */
0097     void clear();
0098 
0099     /**
0100      * invert this BitSet
0101      */
0102     void invert();
0103 
0104     /**
0105      * or this BitSet with another.
0106      * @param other The other BitSet
0107      */
0108     void orBitSet(const BitSet &other);
0109 
0110     /**
0111      * and this BitSet with another.
0112      * @param other The other BitSet
0113      */
0114     void andBitSet(const BitSet &other);
0115 
0116     /**
0117      * see if this BitSet includes another.
0118      * @param other The other BitSet
0119      */
0120     bool includesBitSet(const BitSet &other) const;
0121 
0122     /**
0123      * Assignment operator.
0124      * @param bs BitSet to copy
0125      * @return *this
0126      */
0127     BitSet &operator=(const BitSet &bs);
0128 
0129     /**
0130      * Subtraction assignment operator.
0131      * @param bs BitSet to copy and subtract from this one
0132      * @return *this
0133      */
0134     BitSet &operator-=(const BitSet &bs);
0135 
0136     /**
0137      * Subtraction operator.
0138      * @param bs BitSet to subtract from this one
0139      * @return difference
0140      */
0141     BitSet operator-(const BitSet &bs) const;
0142 
0143     /// Check if all bit are set to 1
0144     bool allOn() const;
0145 
0146     /**
0147      * Check for equality of bitsets
0148      * @param bs BitSet to compare
0149      * @return true if equal
0150      */
0151     bool operator==(const BitSet &bs) const;
0152 
0153     /**
0154      * Opposite of operator ==
0155      */
0156     bool operator!=(const BitSet &bs) const
0157     {
0158         return !operator==(bs);
0159     }
0160 
0161     /**
0162      * Update the number of on bits
0163      */
0164     void updateNumOnBits();
0165 
0166     static BitSet null;
0167 };
0168 
0169 const Uint8 set_on_lookup[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
0170 const Uint8 set_off_lookup[8] = {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE};
0171 
0172 inline bool BitSet::get(Uint32 i) const
0173 {
0174     if (i >= num_bits)
0175         return false;
0176     // i >> 3 equal to i / 8
0177     // i & 7 equal to i % 8
0178     return (data[i >> 3] & set_on_lookup[i & 7]) != 0;
0179 }
0180 
0181 // Fast lookup table to see how many bits are there in a byte
0182 // (macro compacted variant)
0183 static const Uint8 BitCount[256] = {
0184 #define B2(n) n, n + 1, n + 1, n + 2
0185 #define B4(n) B2(n), B2(n + 1), B2(n + 1), B2(n + 2)
0186 #define B6(n) B4(n), B4(n + 1), B4(n + 1), B4(n + 2)
0187     B6(0),
0188     B6(1),
0189     B6(1),
0190     B6(2)};
0191 
0192 inline void BitSet::set(Uint32 i, bool on)
0193 {
0194     if (i >= num_bits)
0195         return;
0196 
0197     Uint8 *d = data + (i >> 3);
0198     num_on -= BitCount[*d];
0199     if (on) {
0200         *d |= set_on_lookup[i & 7];
0201     } else {
0202         *d &= set_off_lookup[i & 7];
0203     }
0204     num_on += BitCount[*d];
0205 }
0206 }
0207 
0208 #endif