source: trunk/lib/bitblock_scan.hpp @ 1675

Last change on this file since 1675 was 1675, checked in by ksherdy, 8 years ago

Added reset() methods to Forward and Reverse scanner classes to allow re-initialization without object constructor overhead.

File size: 3.0 KB
Line 
1/*
2 * bitblock_scan.hpp
3 */
4
5#ifndef BITBLOCK_SCAN_H_
6#define BITBLOCK_SCAN_H_
7
8#include <iterator>
9#include <iostream>
10using namespace std;
11
12#include "bitblock.hpp"
13
14/*
15 * Templated scanner forward and reverse scanner classes on biblock_t, scanblock_t.
16 */ 
17 
18// Base
19template <class bitblock_t, class scanblock_t>
20class Scanner {
21
22protected:
23        Scanner(): strm(NULL), pos(-1), blk(-1), scan_blk(-1) {}
24        Scanner(bitblock_t * s, uint32_t start_pos, uint32_t start_blk, scanblock_t start_scan_blk): strm(s), pos(start_pos), blk(start_blk), scan_blk(start_scan_blk) {}
25
26        bitblock_t * strm;
27        uint32_t pos;
28        uint32_t blk;
29        scanblock_t scan_blk;
30};
31
32// Forward
33template <class bitblock_t, class scanblock_t>
34class ForwardScanner: public Scanner<bitblock_t, scanblock_t> {
35
36public:
37
38        ForwardScanner(): Scanner<bitblock_t, scanblock_t>(){}
39        ForwardScanner(bitblock_t * s): Scanner<bitblock_t, scanblock_t>(s, 0, 0, *((scanblock_t *)s)){}
40
41        IDISA_ALWAYS_INLINE void reset(bitblock_t * s) {
42                Scanner<bitblock_t, scanblock_t>::strm = s;
43                Scanner<bitblock_t, scanblock_t>::pos = 0;
44                Scanner<bitblock_t, scanblock_t>::blk = 0;
45                Scanner<bitblock_t, scanblock_t>::scan_blk = *(scanblock_t *)s;
46        }
47
48        IDISA_ALWAYS_INLINE uint32_t scan_to_next() {
49                while (this->blk < (sizeof(bitblock_t)/sizeof(scanblock_t))){
50                        if(this->scan_blk > 0){
51                                this->pos = count_forward_zeroes(this->scan_blk) + (this->blk * (sizeof(scanblock_t)*8));
52                                this->scan_blk = this->scan_blk & (this->scan_blk-1);  // clear rightmost bit
53
54                                return (this->pos);
55                        }
56
57                        this->blk++;
58                        this->scan_blk = *((scanblock_t *)this->strm + this->blk);
59                };
60
61                this->pos = -1;
62                return (this->pos);
63        }
64
65        IDISA_ALWAYS_INLINE bitblock_t * get_strm() const {return this->strm;}
66        IDISA_ALWAYS_INLINE uint32_t get_pos() const {return this->pos;}
67
68};
69
70// Reverse
71template <class bitblock_t, class scanblock_t>
72class ReverseScanner: public Scanner<bitblock_t, scanblock_t> {
73
74public:
75        ReverseScanner(): Scanner<bitblock_t, scanblock_t>(){}
76        ReverseScanner(bitblock_t * s): Scanner<bitblock_t, scanblock_t>(s, 0, BLOCK_COUNT, *((scanblock_t *)s + (BLOCK_COUNT-1))){}
77
78        IDISA_ALWAYS_INLINE void reset(bitblock_t * s) {
79                Scanner<bitblock_t, scanblock_t>::strm = s;
80                Scanner<bitblock_t, scanblock_t>::pos = 0;
81                Scanner<bitblock_t, scanblock_t>::blk = BLOCK_COUNT;
82                Scanner<bitblock_t, scanblock_t>::scan_blk = *((scanblock_t *)s + (BLOCK_COUNT-1));
83        }
84
85        IDISA_ALWAYS_INLINE uint32_t scan_to_next() {
86                while (this->blk > 0){
87                        if(this->scan_blk > 0){
88                                this->pos = (sizeof(scanblock_t)*8 - count_reverse_zeroes(this->scan_blk) -1) + ( (this->blk-1) * sizeof(scanblock_t)*8 );
89                                this->scan_blk = this->scan_blk ^ (1 << this->pos); // clear leftmost bit
90                                return (this->pos);
91                        }
92
93                        this->blk--;
94                        this->scan_blk = *((scanblock_t *)this->strm + this->blk-1);
95                };
96
97                this->pos = -1;
98                return (this->pos);
99        }
100
101        IDISA_ALWAYS_INLINE bitblock_t * get_strm() const {return this->strm;}
102        IDISA_ALWAYS_INLINE uint32_t get_pos() const {return this->pos;}
103
104        static const uint32_t BLOCK_COUNT = sizeof(bitblock_t)/sizeof(scanblock_t);
105
106};
107
108
109#endif /* BITBLOCK_SCAN_H_ */
110
Note: See TracBrowser for help on using the repository browser.