1 #ifndef __BITARRAY__ //数组不支持多线程同时访问,没有对引用计数以及分配的资源做任何锁处理 2 #define __BITARRAY__ 1 //越界访问修改为抛出异常 3 4 #ifdef __BIT_DEBUG__ //__BIT_DEBUG__是调试用的宏定义 5 #include <cstdio> 6 #endif 7 8 #ifdef __cplusplus > 201103L 9 #include <cstdint> 10 #else 11 #include <stdint.h> 12 #define nullptr NULL 13 #define noexcept throw() 14 #endif 15 16 #define __BIT_ERRMSG_LEN__ 512 17 18 #include <cstring> 19 #include <stdexcept> 20 21 class BitArray 22 { 23 private: 24 enum __e_bit_size {bit = 8}; 25 26 class __Ref_Array //引用计数类 27 { 28 public: 29 __Ref_Array(int64_t __size) 30 :m_ref_count(0), m_size(__size) 31 { 32 #ifdef __BIT_DEBUG__ 33 fprintf(stderr, "__Ref_Array ctor @addr: %p with size:%ld\n", this, __size); 34 #endif 35 init(); 36 } 37 38 ~__Ref_Array() 39 { 40 #ifdef __BIT_DEBUG__ 41 fprintf(stderr, "__Ref_Array dtor @addr: %p with size:%ld\n", this, __size); 42 #endif 43 delete[] m_array; 44 } 45 46 __Ref_Array(const __Ref_Array& o) 47 :m_ref_count(1), 48 m_size(o.m_size), 49 m_array_size(o.m_array_size), 50 m_used(o.m_used) 51 { 52 #ifdef __BIT_DEBUG__ 53 fprintf(stderr, "__Ref_Array copytor @addr: %p with @addr: %p && size:%ld\n", this, &o, __size); 54 #endif 55 m_array = new int8_t[m_array_size]; 56 memcpy(m_array, o.m_array, m_array_size); 57 } 58 59 inline bool 60 get(int64_t __pos) const 61 {return *(m_array + slot_bit(__pos)) & mask(__pos);} 62 63 inline void 64 set(int64_t __pos) 65 { 66 *(m_array + slot_bit(__pos)) |= mask(__pos); 67 m_used ++; 68 } 69 70 inline void 71 clear(int64_t __pos) 72 { 73 *(m_array + slot_bit(__pos)) &= ~mask(__pos); 74 m_used --; 75 } 76 77 inline void 78 reset() 79 { 80 std::memset(m_array, 0, m_array_size); 81 m_used = 0; 82 } 83 84 inline int64_t 85 length() const 86 {return m_size;} 87 88 inline int64_t 89 size() const 90 {return m_size;} 91 92 inline int64_t 93 used() const 94 {return m_used;} 95 96 inline int64_t 97 refCount() const 98 {return m_ref_count;} 99 100 inline bool 101 sizeRange(int64_t __pos) const 102 {return __pos >= 0 && __pos < m_size;} 103 104 inline int64_t 105 sharedPlus() 106 {return ++ m_ref_count;} 107 108 inline int64_t 109 sharedSub() 110 {return -- m_ref_count;} 111 112 inline bool 113 isShared() const 114 {return m_ref_count > 1;} 115 116 private: 117 inline void 118 init() 119 { 120 m_array_size = nslot(m_size); 121 m_array = new int8_t[m_array_size]; 122 reset(); 123 } 124 125 inline int64_t 126 slot_bit(int64_t __n) const 127 {return __n / bit;} 128 129 inline int64_t 130 nslot(int64_t __size) const 131 {return slot_bit(__size + bit - 1);} 132 133 inline int8_t 134 mask(int64_t __pos) const 135 {return int8_t(1) << (__pos % bit);} 136 137 private: 138 int8_t m_array; //位数组存储 139 int64_t m_ref_count; //引用计数 140 int64_t m_size; //引用计数大小 141 int64_t m_array_size; //分配的int8_t数组大小 142 int64_t m_used; //已经使用的bit位数 143 }; 144 145 private: 146 class BitProxy //代理类 为了区分 x = ba[?]; 和 ba[?]; 147 { 148 BitProxy(BitArray& ba, int64_t pos) 149 :m_array(ba), m_pos(pos) 150 {} 151 152 BitProxy& operator = (const BitProxy& rh) 153 { 154 if(rh) 155 m_array.set(m_pos); 156 else{ 157 m_array.clear(m_pos); 158 } 159 160 return *this; 161 } 162 163 BitProxy& operator = (bool status) 164 { 165 if(status) 166 m_array.set(m_pos); 167 else{ 168 m_array.clear(m_pos); 169 } 170 171 return *this; 172 } 173 174 operator bool() const 175 { 176 return m_array.get(m_pos); 177 } 178 179 private: 180 BitArray& m_array; 181 int64_t m_pos; 182 }; 183 184 public: 185 186 BitArray() noexcept //无参数构造函数 187 :m_ref(nullptr) 188 { 189 #ifdef __BIT_DEBUG__ 190 fprintf(stderr, "BitArray ctor @addr: %p with nullptr ...\n", this); 191 #endif 192 } 193 194 BitArray(int64_t size) noexcept //构造函数 195 :m_ref(size > 0 new __Ref_Array(size) : nullptr) 196 { 197 #ifdef __BIT_DEBUG__ 198 fprintf(stderr, "BitArray ctor @addr: %p with size: %d ...\n", this, size); 199 #endif 200 } 201 202 ~BitArray() //析构函数 203 {release()} 204 205 BitArray(const BitArray& o) noexcept //copy构造函数 206 m_ref(o.m_ref) 207 { 208 #ifdef __BIT_DEBUG__ 209 fprintf(stderr, "BitArray copy tor @addr: %p with other BitArray @addr: %p ...\n", this, &o); 210 #endif 211 } 212 213 #ifdef __cplusplus >= 201103L 214 BitArray(BitArray&& o) noexcept //move构造函数 215 m_ref(o.m_ref) 216 { 217 #ifdef __BIT_DEBUG__ 218 fprintf(stderr, "BitArray move tor @addr: %p <--- other BitArray @addr: %p ...\n", this, &o); 219 #endif 220 o.m_ref = nullptr; 221 } 222 #endif 223 224 BitArray& operator=(const BitArray& o) //赋值运算符 225 { 226 if(m_ref != o.m_ref) 227 { 228 release(); 229 m_ref = o.m_ref; 230 #ifdef __BIT_DEBUG__ 231 fprintf(stderr, "BitArray assign @addr: %p with other BitArray @addr: %p ...\n", this, &o); 232 #endif 233 if(m_ref) 234 m_ref->sharedPlus(); 235 } 236 } 237 238 const BitProxy 239 operator[] (int64_t pos) const //下标运算符 240 {return BitProxy(const_cast<BitArray&>(*this), pos);} 241 242 BitProxy 243 operator[] (int64_t pos) //下标运算符 244 {return BitProxy(*this, pos);} 245 246 public: 247 inline bool 248 get(int64_t pos) const throw(std::out_of_range) 249 { 250 if(!m_ref || !m_ref->sizeRange(pos)) 251 { 252 char errmsg[__BIT_ERRMSG_LEN__] = {0}; 253 254 snprintf(errmsg, sizeof(errmsg), "out of range in get -> pos : %d | size : %d\n", pos, size()); 255 256 throw std::out_of_range(errmsg); 257 } 258 else 259 return m_ref->get(pos); 260 } 261 262 inline bool 263 set(int64_t pos) const throw(std::out_of_range) 264 { 265 if(!m_ref || !m_ref->sizeRange(pos)) 266 { 267 char errmsg[__BIT_ERRMSG_LEN__] = {0}; 268 269 snprintf(errmsg, sizeof(errmsg), "out of range in set -> pos : %d | size : %d\n", pos, size()); 270 271 throw std::out_of_range(errmsg); 272 } 273 else if(m_ref->get(pos)) 274 { 275 return true; 276 } 277 else 278 { 279 if(m_ref->isShared()) 280 { 281 __Ref_Array* last_ref = m_ref; 282 283 m_ref = new __Ref_Array(*last_ref); 284 285 last_ref->sharedSub(); 286 } 287 288 return m_ref->get(pos); 289 } 290 } 291 292 293 inline bool 294 clear(int64_t pos) const throw(std::out_of_range) 295 { 296 if(!m_ref || !m_ref->sizeRange(pos)) 297 { 298 char errmsg[__BIT_ERRMSG_LEN__] = {0}; 299 300 snprintf(errmsg, sizeof(errmsg), "out of range in clear -> pos : %d | size : %d\n", pos, size()); 301 302 throw std::out_of_range(errmsg); 303 } 304 else if(!m_ref->get(pos)) 305 { 306 return true; 307 } 308 else 309 { 310 if(m_ref->isShared()) 311 { 312 __Ref_Array* last_ref = m_ref; 313 314 m_ref = new __Ref_Array(*last_ref); 315 316 last_ref->sharedSub(); 317 } 318 319 return m_ref->clear(pos); 320 } 321 } 322 323 inline void 324 reset() 325 {if(m_ref) m_ref->reset();} 326 327 inline int64_t 328 size() 329 {return m_ref ? m_ref->size() : 0;} 330 331 inline int64_t 332 length() 333 {return m_ref ? m_ref->length() : 0;} 334 335 inline int64_t 336 count() 337 {return m_ref ? m_ref->count() : 0;} 338 private: 339 inline void 340 release() //引用计数释放 341 { 342 #ifdef __BIT_DEBUG__ 343 fprintf(stderr, "BitArray released @addr: %p current reference : %d ...\n", this, m_ref->refCount()); 344 #endif 345 if(m_ref && (m_ref->sharedSub() == 0)) 346 { 347 delete m_ref; 348 m_ref = null; 349 } 350 } 351 352 __Ref_Array* m_ref; 353 }; 354 355 #endif