Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/harfbuzz/src/hb-bimap.hh
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2019 Adobe Inc.
3
 *
4
 *  This is part of HarfBuzz, a text shaping library.
5
 *
6
 * Permission is hereby granted, without written agreement and without
7
 * license or royalty fees, to use, copy, modify, and distribute this
8
 * software and its documentation for any purpose, provided that the
9
 * above copyright notice and the following two paragraphs appear in
10
 * all copies of this software.
11
 *
12
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16
 * DAMAGE.
17
 *
18
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23
 *
24
 * Adobe Author(s): Michiharu Ariza
25
 */
26
27
#ifndef HB_BIMAP_HH
28
#define HB_BIMAP_HH
29
30
#include "hb.hh"
31
#include "hb-map.hh"
32
33
/* Bi-directional map */
34
struct hb_bimap_t
35
{
36
  void reset ()
37
0
  {
38
0
    forw_map.reset ();
39
0
    back_map.reset ();
40
0
  }
41
42
  void alloc (unsigned pop)
43
0
  {
44
0
    forw_map.alloc (pop);
45
0
    back_map.alloc (pop);
46
0
  }
47
48
0
  bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
49
50
  void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
51
0
  {
52
0
    if (in_error ()) return;
53
0
    if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return;
54
0
    if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
55
0
56
0
    forw_map.set (lhs, rhs);
57
0
    if (unlikely (in_error ())) return;
58
0
59
0
    back_map.set (rhs, lhs);
60
0
    if (unlikely (in_error ())) forw_map.del (lhs);
61
0
  }
62
63
0
  hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
64
0
  hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); }
65
66
0
  hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
67
0
  bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); }
68
69
70
  void del (hb_codepoint_t lhs)
71
0
  {
72
0
    back_map.del (get (lhs));
73
0
    forw_map.del (lhs);
74
0
  }
75
76
  void clear ()
77
0
  {
78
0
    forw_map.clear ();
79
0
    back_map.clear ();
80
0
  }
81
82
0
  bool is_empty () const { return forw_map.is_empty (); }
83
84
0
  unsigned int get_population () const { return forw_map.get_population (); }
85
86
  protected:
87
  hb_map_t  forw_map;
88
  hb_map_t  back_map;
89
90
  public:
91
  auto keys () const HB_AUTO_RETURN (+ forw_map.keys())
92
  auto values () const HB_AUTO_RETURN (+ forw_map.values())
93
  auto iter () const HB_AUTO_RETURN (+ forw_map.iter())
94
};
95
96
/* Incremental bimap: only lhs is given, rhs is incrementally assigned */
97
struct hb_inc_bimap_t
98
{
99
0
  bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
100
101
0
  unsigned int get_population () const { return forw_map.get_population (); }
102
103
  void reset ()
104
0
  {
105
0
    forw_map.reset ();
106
0
    back_map.reset ();
107
0
  }
108
109
  void alloc (unsigned pop)
110
0
  {
111
0
    forw_map.alloc (pop);
112
0
    back_map.alloc (pop);
113
0
  }
114
115
  void clear ()
116
0
  {
117
0
    forw_map.clear ();
118
0
    back_map.resize (0);
119
0
  }
120
121
  /* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
122
   * Return the rhs value as the result.
123
   */
124
  hb_codepoint_t add (hb_codepoint_t lhs)
125
0
  {
126
0
    hb_codepoint_t  rhs = forw_map[lhs];
127
0
    if (rhs == HB_MAP_VALUE_INVALID)
128
0
    {
129
0
      rhs = back_map.length;
130
0
      forw_map.set (lhs, rhs);
131
0
      back_map.push (lhs);
132
0
    }
133
0
    return rhs;
134
0
  }
135
136
  hb_codepoint_t skip ()
137
0
  {
138
0
    hb_codepoint_t start = back_map.length;
139
0
    back_map.push (HB_MAP_VALUE_INVALID);
140
0
    return start;
141
0
  }
142
143
  hb_codepoint_t skip (unsigned count)
144
0
  {
145
0
    hb_codepoint_t start = back_map.length;
146
0
    back_map.alloc (back_map.length + count);
147
0
    for (unsigned i = 0; i < count; i++)
148
0
      back_map.push (HB_MAP_VALUE_INVALID);
149
0
    return start;
150
0
  }
151
152
  hb_codepoint_t get_next_value () const
153
0
  { return back_map.length; }
154
155
  void add_set (const hb_set_t *set)
156
0
  {
157
0
    for (auto i : *set) add (i);
158
0
  }
159
160
  /* Create an identity map. */
161
  bool identity (unsigned int size)
162
0
  {
163
0
    clear ();
164
0
    for (hb_codepoint_t i = 0; i < size; i++) add (i);
165
0
    return !in_error ();
166
0
  }
167
168
  protected:
169
  static int cmp_id (const void* a, const void* b)
170
0
  { return (int)*(const hb_codepoint_t *)a - (int)*(const hb_codepoint_t *)b; }
171
172
  public:
173
  /* Optional: after finished adding all mappings in a random order,
174
   * reassign rhs to lhs so that they are in the same order. */
175
  void sort ()
176
0
  {
177
0
    hb_codepoint_t  count = get_population ();
178
0
    hb_vector_t <hb_codepoint_t> work;
179
0
    if (unlikely (!work.resize (count, false))) return;
180
0
181
0
    for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
182
0
      work.arrayZ[rhs] = back_map[rhs];
183
0
184
0
    work.qsort (cmp_id);
185
0
186
0
    clear ();
187
0
    for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
188
0
      add (work.arrayZ[rhs]);
189
0
  }
190
191
0
  hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
192
0
  hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map[rhs]; }
193
194
0
  hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
195
0
  bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); }
196
197
  protected:
198
  hb_map_t forw_map;
199
  hb_vector_t<hb_codepoint_t> back_map;
200
201
  public:
202
  auto keys () const HB_AUTO_RETURN (+ back_map.iter())
203
};
204
205
#endif /* HB_BIMAP_HH */