Copyright 2013 -> 2014
[folly.git] / folly / detail / BitIteratorDetail.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef FOLLY_DETAIL_BITITERATORDETAIL_H_
18 #define FOLLY_DETAIL_BITITERATORDETAIL_H_
19
20 #include <iterator>
21 #include <type_traits>
22 #include <boost/iterator/iterator_adaptor.hpp>
23
24 namespace folly {
25
26 template <class BaseIter> class BitIterator;
27
28 namespace bititerator_detail {
29
30 // Reference to a bit.
31 // Templatize on both parent reference and value types to capture
32 // const-ness correctly and to work with the case where Ref is a
33 // reference-like type (not T&), just like our BitReference here.
34 template <class Ref, class Value>
35 class BitReference {
36  public:
37   BitReference(Ref r, size_t bit) : ref_(r), bit_(bit) { }
38
39   operator bool() const {
40     return ref_ & (one_ << bit_);
41   }
42
43   BitReference& operator=(bool b) {
44     if (b) {
45       set();
46     } else {
47       clear();
48     }
49     return *this;
50   }
51
52   void set() {
53     ref_ |= (one_ << bit_);
54   }
55
56   void clear() {
57     ref_ &= ~(one_ << bit_);
58   }
59
60   void flip() {
61     ref_ ^= (one_ << bit_);
62   }
63
64  private:
65   // shortcut to avoid writing static_cast everywhere
66   const static Value one_ = 1;
67
68   Ref ref_;
69   size_t bit_;
70 };
71
72 template <class BaseIter>
73 struct BitIteratorBase {
74   static_assert(std::is_integral<typename BaseIter::value_type>::value,
75                 "BitIterator may only be used with integral types");
76   typedef boost::iterator_adaptor<
77     BitIterator<BaseIter>,      // Derived
78     BaseIter,                   // Base
79     bool,                       // Value
80     boost::use_default,         // CategoryOrTraversal
81     bititerator_detail::BitReference<
82       typename std::iterator_traits<BaseIter>::reference,
83       typename std::iterator_traits<BaseIter>::value_type
84     >,  // Reference
85     ssize_t> type;
86 };
87
88
89 }  // namespace bititerator_detail
90 }  // namespace folly
91
92 #endif /* FOLLY_DETAIL_BITITERATORDETAIL_H_ */
93