xref: /aosp_15_r20/external/regex-re2/re2/bitmap256.h (revision ccdc9c3e24c519bfa4832a66aa2e83a52c19f295)
1*ccdc9c3eSSadaf Ebrahimi // Copyright 2016 The RE2 Authors.  All Rights Reserved.
2*ccdc9c3eSSadaf Ebrahimi // Use of this source code is governed by a BSD-style
3*ccdc9c3eSSadaf Ebrahimi // license that can be found in the LICENSE file.
4*ccdc9c3eSSadaf Ebrahimi 
5*ccdc9c3eSSadaf Ebrahimi #ifndef RE2_BITMAP256_H_
6*ccdc9c3eSSadaf Ebrahimi #define RE2_BITMAP256_H_
7*ccdc9c3eSSadaf Ebrahimi 
8*ccdc9c3eSSadaf Ebrahimi #ifdef _MSC_VER
9*ccdc9c3eSSadaf Ebrahimi #include <intrin.h>
10*ccdc9c3eSSadaf Ebrahimi #endif
11*ccdc9c3eSSadaf Ebrahimi #include <stdint.h>
12*ccdc9c3eSSadaf Ebrahimi #include <string.h>
13*ccdc9c3eSSadaf Ebrahimi 
14*ccdc9c3eSSadaf Ebrahimi #include "util/util.h"
15*ccdc9c3eSSadaf Ebrahimi #include "util/logging.h"
16*ccdc9c3eSSadaf Ebrahimi 
17*ccdc9c3eSSadaf Ebrahimi namespace re2 {
18*ccdc9c3eSSadaf Ebrahimi 
19*ccdc9c3eSSadaf Ebrahimi class Bitmap256 {
20*ccdc9c3eSSadaf Ebrahimi  public:
Bitmap256()21*ccdc9c3eSSadaf Ebrahimi   Bitmap256() {
22*ccdc9c3eSSadaf Ebrahimi     memset(words_, 0, sizeof words_);
23*ccdc9c3eSSadaf Ebrahimi   }
24*ccdc9c3eSSadaf Ebrahimi 
25*ccdc9c3eSSadaf Ebrahimi   // Tests the bit with index c.
Test(int c)26*ccdc9c3eSSadaf Ebrahimi   bool Test(int c) const {
27*ccdc9c3eSSadaf Ebrahimi     DCHECK_GE(c, 0);
28*ccdc9c3eSSadaf Ebrahimi     DCHECK_LE(c, 255);
29*ccdc9c3eSSadaf Ebrahimi 
30*ccdc9c3eSSadaf Ebrahimi     return (words_[c / 64] & (1ULL << (c % 64))) != 0;
31*ccdc9c3eSSadaf Ebrahimi   }
32*ccdc9c3eSSadaf Ebrahimi 
33*ccdc9c3eSSadaf Ebrahimi   // Sets the bit with index c.
Set(int c)34*ccdc9c3eSSadaf Ebrahimi   void Set(int c) {
35*ccdc9c3eSSadaf Ebrahimi     DCHECK_GE(c, 0);
36*ccdc9c3eSSadaf Ebrahimi     DCHECK_LE(c, 255);
37*ccdc9c3eSSadaf Ebrahimi 
38*ccdc9c3eSSadaf Ebrahimi     words_[c / 64] |= (1ULL << (c % 64));
39*ccdc9c3eSSadaf Ebrahimi   }
40*ccdc9c3eSSadaf Ebrahimi 
41*ccdc9c3eSSadaf Ebrahimi   // Finds the next non-zero bit with index >= c.
42*ccdc9c3eSSadaf Ebrahimi   // Returns -1 if no such bit exists.
43*ccdc9c3eSSadaf Ebrahimi   int FindNextSetBit(int c) const;
44*ccdc9c3eSSadaf Ebrahimi 
45*ccdc9c3eSSadaf Ebrahimi  private:
46*ccdc9c3eSSadaf Ebrahimi   // Finds the least significant non-zero bit in n.
FindLSBSet(uint64_t n)47*ccdc9c3eSSadaf Ebrahimi   static int FindLSBSet(uint64_t n) {
48*ccdc9c3eSSadaf Ebrahimi     DCHECK_NE(n, 0);
49*ccdc9c3eSSadaf Ebrahimi 
50*ccdc9c3eSSadaf Ebrahimi #if defined(__GNUC__)
51*ccdc9c3eSSadaf Ebrahimi     return __builtin_ctzll(n);
52*ccdc9c3eSSadaf Ebrahimi #elif defined(_MSC_VER) && defined(_M_X64)
53*ccdc9c3eSSadaf Ebrahimi     unsigned long c;
54*ccdc9c3eSSadaf Ebrahimi     _BitScanForward64(&c, n);
55*ccdc9c3eSSadaf Ebrahimi     return static_cast<int>(c);
56*ccdc9c3eSSadaf Ebrahimi #elif defined(_MSC_VER) && defined(_M_IX86)
57*ccdc9c3eSSadaf Ebrahimi     unsigned long c;
58*ccdc9c3eSSadaf Ebrahimi     if (static_cast<uint32_t>(n) != 0) {
59*ccdc9c3eSSadaf Ebrahimi       _BitScanForward(&c, static_cast<uint32_t>(n));
60*ccdc9c3eSSadaf Ebrahimi       return static_cast<int>(c);
61*ccdc9c3eSSadaf Ebrahimi     } else {
62*ccdc9c3eSSadaf Ebrahimi       _BitScanForward(&c, static_cast<uint32_t>(n >> 32));
63*ccdc9c3eSSadaf Ebrahimi       return static_cast<int>(c) + 32;
64*ccdc9c3eSSadaf Ebrahimi     }
65*ccdc9c3eSSadaf Ebrahimi #else
66*ccdc9c3eSSadaf Ebrahimi     int c = 63;
67*ccdc9c3eSSadaf Ebrahimi     for (int shift = 1 << 5; shift != 0; shift >>= 1) {
68*ccdc9c3eSSadaf Ebrahimi       uint64_t word = n << shift;
69*ccdc9c3eSSadaf Ebrahimi       if (word != 0) {
70*ccdc9c3eSSadaf Ebrahimi         n = word;
71*ccdc9c3eSSadaf Ebrahimi         c -= shift;
72*ccdc9c3eSSadaf Ebrahimi       }
73*ccdc9c3eSSadaf Ebrahimi     }
74*ccdc9c3eSSadaf Ebrahimi     return c;
75*ccdc9c3eSSadaf Ebrahimi #endif
76*ccdc9c3eSSadaf Ebrahimi   }
77*ccdc9c3eSSadaf Ebrahimi 
78*ccdc9c3eSSadaf Ebrahimi   uint64_t words_[4];
79*ccdc9c3eSSadaf Ebrahimi };
80*ccdc9c3eSSadaf Ebrahimi 
FindNextSetBit(int c)81*ccdc9c3eSSadaf Ebrahimi int Bitmap256::FindNextSetBit(int c) const {
82*ccdc9c3eSSadaf Ebrahimi   DCHECK_GE(c, 0);
83*ccdc9c3eSSadaf Ebrahimi   DCHECK_LE(c, 255);
84*ccdc9c3eSSadaf Ebrahimi 
85*ccdc9c3eSSadaf Ebrahimi   // Check the word that contains the bit. Mask out any lower bits.
86*ccdc9c3eSSadaf Ebrahimi   int i = c / 64;
87*ccdc9c3eSSadaf Ebrahimi   uint64_t word = words_[i] & (~0ULL << (c % 64));
88*ccdc9c3eSSadaf Ebrahimi   if (word != 0)
89*ccdc9c3eSSadaf Ebrahimi     return (i * 64) + FindLSBSet(word);
90*ccdc9c3eSSadaf Ebrahimi 
91*ccdc9c3eSSadaf Ebrahimi   // Check any following words.
92*ccdc9c3eSSadaf Ebrahimi   i++;
93*ccdc9c3eSSadaf Ebrahimi   switch (i) {
94*ccdc9c3eSSadaf Ebrahimi     case 1:
95*ccdc9c3eSSadaf Ebrahimi       if (words_[1] != 0)
96*ccdc9c3eSSadaf Ebrahimi         return (1 * 64) + FindLSBSet(words_[1]);
97*ccdc9c3eSSadaf Ebrahimi       FALLTHROUGH_INTENDED;
98*ccdc9c3eSSadaf Ebrahimi     case 2:
99*ccdc9c3eSSadaf Ebrahimi       if (words_[2] != 0)
100*ccdc9c3eSSadaf Ebrahimi         return (2 * 64) + FindLSBSet(words_[2]);
101*ccdc9c3eSSadaf Ebrahimi       FALLTHROUGH_INTENDED;
102*ccdc9c3eSSadaf Ebrahimi     case 3:
103*ccdc9c3eSSadaf Ebrahimi       if (words_[3] != 0)
104*ccdc9c3eSSadaf Ebrahimi         return (3 * 64) + FindLSBSet(words_[3]);
105*ccdc9c3eSSadaf Ebrahimi       FALLTHROUGH_INTENDED;
106*ccdc9c3eSSadaf Ebrahimi     default:
107*ccdc9c3eSSadaf Ebrahimi       return -1;
108*ccdc9c3eSSadaf Ebrahimi   }
109*ccdc9c3eSSadaf Ebrahimi }
110*ccdc9c3eSSadaf Ebrahimi 
111*ccdc9c3eSSadaf Ebrahimi }  // namespace re2
112*ccdc9c3eSSadaf Ebrahimi 
113*ccdc9c3eSSadaf Ebrahimi #endif  // RE2_BITMAP256_H_
114