Coverage Report

Created: 2025-07-11 06:34

/src/harfbuzz/src/hb-bit-vector.hh
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  This is part of HarfBuzz, a text shaping library.
3
 *
4
 * Permission is hereby granted, without written agreement and without
5
 * license or royalty fees, to use, copy, modify, and distribute this
6
 * software and its documentation for any purpose, provided that the
7
 * above copyright notice and the following two paragraphs appear in
8
 * all copies of this software.
9
 *
10
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
11
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
12
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
13
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
14
 * DAMAGE.
15
 *
16
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
17
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
19
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
20
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
21
 *
22
 * Author(s): Behdad Esfahbod
23
 */
24
25
#ifndef HB_BIT_VECTOR_HH
26
#define HB_BIT_VECTOR_HH
27
28
#include "hb.hh"
29
30
#include "hb-atomic.hh"
31
32
struct hb_min_max_t
33
{
34
0
  void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); }
35
  void add_range (hb_codepoint_t a, hb_codepoint_t b)
36
0
  {
37
0
    min_v = hb_min (min_v, a);
38
0
    max_v = hb_max (max_v, b);
39
0
  }
40
41
  template <typename set_t>
42
  void union_ (const set_t &set)
43
  {
44
    hb_codepoint_t set_min = set.get_min ();
45
    if (unlikely (set_min == HB_CODEPOINT_INVALID))
46
      return;
47
    hb_codepoint_t set_max = set.get_max ();
48
    min_v = hb_min (min_v, set_min);
49
    max_v = hb_max (max_v, set_max);
50
  }
51
52
0
  hb_codepoint_t get_min () const { return min_v; }
53
0
  hb_codepoint_t get_max () const { return max_v; }
54
55
  private:
56
  hb_codepoint_t min_v = HB_CODEPOINT_INVALID;
57
  hb_codepoint_t max_v = 0;
58
};
59
60
template <bool atomic = false>
61
struct hb_bit_vector_t
62
{
63
  using int_t = uint64_t;
64
  using elt_t = typename std::conditional<atomic, hb_atomic_t<int_t>, int_t>::type;
65
66
  hb_bit_vector_t () = delete;
67
  hb_bit_vector_t (const hb_bit_vector_t &other) = delete;
68
  hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete;
69
70
  // Move
71
  hb_bit_vector_t (hb_bit_vector_t &&other)
72
    : min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts)
73
  {
74
    other.min_v = other.max_v = other.count = 0;
75
    other.elts = nullptr;
76
  }
77
  hb_bit_vector_t &operator= (hb_bit_vector_t &&other)
78
  {
79
    hb_swap (min_v, other.min_v);
80
    hb_swap (max_v, other.max_v);
81
    hb_swap (count, other.count);
82
    hb_swap (elts, other.elts);
83
    return *this;
84
  }
85
86
  hb_bit_vector_t (unsigned min_v, unsigned max_v)
87
    : min_v (min_v), max_v (max_v)
88
  {
89
    if (unlikely (min_v >= max_v))
90
    {
91
      min_v = max_v = count = 0;
92
      return;
93
    }
94
95
    unsigned num = (max_v - min_v + sizeof (int_t) * 8) / (sizeof (int_t) * 8);
96
    elts = (elt_t *) hb_calloc (num, sizeof (int_t));
97
    if (unlikely (!elts))
98
    {
99
      min_v = max_v = count = 0;
100
      return;
101
    }
102
103
    count = max_v - min_v + 1;
104
  }
105
  ~hb_bit_vector_t ()
106
  {
107
    hb_free (elts);
108
  }
109
110
  void add (hb_codepoint_t g) { elt (g) |= mask (g); }
111
  void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
112
  void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
113
  bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
114
  bool has (hb_codepoint_t g) const { return get (g); }
115
  bool may_have (hb_codepoint_t g) const { return get (g); }
116
117
  bool operator [] (hb_codepoint_t g) const { return get (g); }
118
  bool operator () (hb_codepoint_t g) const { return get (g); }
119
120
  void add_range (hb_codepoint_t a, hb_codepoint_t b)
121
  {
122
    if (unlikely (!count || a > b || a < min_v || b > max_v))
123
      return;
124
125
    elt_t *la = &elt (a);
126
    elt_t *lb = &elt (b);
127
    if (la == lb)
128
      *la |= (mask (b) << 1) - mask(a);
129
    else
130
    {
131
      *la |= ~(mask (a) - 1llu);
132
      la++;
133
134
      hb_memset (la, 0xff, (char *) lb - (char *) la);
135
136
      *lb |= ((mask (b) << 1) - 1llu);
137
    }
138
  }
139
  void del_range (hb_codepoint_t a, hb_codepoint_t b)
140
  {
141
    if (unlikely (!count || a > b || a < min_v || b > max_v))
142
      return;
143
144
    elt_t *la = &elt (a);
145
    elt_t *lb = &elt (b);
146
    if (la == lb)
147
      *la &= ~((mask (b) << 1llu) - mask(a));
148
    else
149
    {
150
      *la &= mask (a) - 1;
151
      la++;
152
153
      hb_memset (la, 0, (char *) lb - (char *) la);
154
155
      *lb &= ~((mask (b) << 1) - 1llu);
156
    }
157
  }
158
  void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
159
  { if (v) add_range (a, b); else del_range (a, b); }
160
161
  template <typename set_t>
162
  void union_ (const set_t &set)
163
  {
164
    for (hb_codepoint_t g : set)
165
      add (g);
166
  }
167
168
  static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
169
  static constexpr unsigned ELT_MASK = ELT_BITS - 1;
170
171
  static constexpr elt_t zero = 0;
172
173
  elt_t &elt (hb_codepoint_t g)
174
  {
175
    g -= min_v;
176
    if (unlikely (g >= count))
177
      return Crap(elt_t);
178
    return elts[g / ELT_BITS];
179
  }
180
  const elt_t& elt (hb_codepoint_t g) const
181
  {
182
    g -= min_v;
183
    if (unlikely (g >= count))
184
      return Null(elt_t);
185
    return elts[g / ELT_BITS];
186
  }
187
188
  static constexpr int_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); }
189
190
  hb_codepoint_t min_v = 0, max_v = 0, count = 0;
191
  elt_t *elts = nullptr;
192
};
193
194
195
#endif /* HB_BIT_VECTOR_HH */