2 * Copyright © 2019 Adobe Inc.
4 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
24 * Adobe Author(s): Michiharu Ariza
33 /* Bi-directional map */
42 void alloc (unsigned pop
)
48 bool in_error () const { return forw_map
.in_error () || back_map
.in_error (); }
50 void set (hb_codepoint_t lhs
, hb_codepoint_t rhs
)
52 if (in_error ()) return;
53 if (unlikely (lhs
== HB_MAP_VALUE_INVALID
)) return;
54 if (unlikely (rhs
== HB_MAP_VALUE_INVALID
)) { del (lhs
); return; }
56 forw_map
.set (lhs
, rhs
);
57 if (unlikely (in_error ())) return;
59 back_map
.set (rhs
, lhs
);
60 if (unlikely (in_error ())) forw_map
.del (lhs
);
63 hb_codepoint_t
get (hb_codepoint_t lhs
) const { return forw_map
.get (lhs
); }
64 hb_codepoint_t
backward (hb_codepoint_t rhs
) const { return back_map
.get (rhs
); }
66 hb_codepoint_t
operator [] (hb_codepoint_t lhs
) const { return get (lhs
); }
67 bool has (hb_codepoint_t lhs
) const { return forw_map
.has (lhs
); }
70 void del (hb_codepoint_t lhs
)
72 back_map
.del (get (lhs
));
82 bool is_empty () const { return forw_map
.is_empty (); }
84 unsigned int get_population () const { return forw_map
.get_population (); }
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())
96 /* Incremental bimap: only lhs is given, rhs is incrementally assigned */
99 bool in_error () const { return forw_map
.in_error () || back_map
.in_error (); }
101 unsigned int get_population () const { return forw_map
.get_population (); }
109 void alloc (unsigned pop
)
111 forw_map
.alloc (pop
);
112 back_map
.alloc (pop
);
121 /* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
122 * Return the rhs value as the result.
124 hb_codepoint_t
add (hb_codepoint_t lhs
)
126 hb_codepoint_t rhs
= forw_map
[lhs
];
127 if (rhs
== HB_MAP_VALUE_INVALID
)
129 rhs
= back_map
.length
;
130 forw_map
.set (lhs
, rhs
);
136 hb_codepoint_t
skip ()
138 hb_codepoint_t start
= back_map
.length
;
139 back_map
.push (HB_MAP_VALUE_INVALID
);
143 hb_codepoint_t
skip (unsigned count
)
145 hb_codepoint_t start
= back_map
.length
;
146 back_map
.alloc (back_map
.length
+ count
);
147 for (unsigned i
= 0; i
< count
; i
++)
148 back_map
.push (HB_MAP_VALUE_INVALID
);
152 hb_codepoint_t
get_next_value () const
153 { return back_map
.length
; }
155 void add_set (const hb_set_t
*set
)
157 for (auto i
: *set
) add (i
);
160 /* Create an identity map. */
161 bool identity (unsigned int size
)
164 for (hb_codepoint_t i
= 0; i
< size
; i
++) add (i
);
169 static int cmp_id (const void* a
, const void* b
)
170 { return (int)*(const hb_codepoint_t
*)a
- (int)*(const hb_codepoint_t
*)b
; }
173 /* Optional: after finished adding all mappings in a random order,
174 * reassign rhs to lhs so that they are in the same order. */
177 hb_codepoint_t count
= get_population ();
178 hb_vector_t
<hb_codepoint_t
> work
;
179 if (unlikely (!work
.resize (count
, false))) return;
181 for (hb_codepoint_t rhs
= 0; rhs
< count
; rhs
++)
182 work
.arrayZ
[rhs
] = back_map
[rhs
];
187 for (hb_codepoint_t rhs
= 0; rhs
< count
; rhs
++)
188 add (work
.arrayZ
[rhs
]);
191 hb_codepoint_t
get (hb_codepoint_t lhs
) const { return forw_map
.get (lhs
); }
192 hb_codepoint_t
backward (hb_codepoint_t rhs
) const { return back_map
[rhs
]; }
194 hb_codepoint_t
operator [] (hb_codepoint_t lhs
) const { return get (lhs
); }
195 bool has (hb_codepoint_t lhs
) const { return forw_map
.has (lhs
); }
199 hb_vector_t
<hb_codepoint_t
> back_map
;
202 auto keys () const HB_AUTO_RETURN (+ back_map
.iter())
205 #endif /* HB_BIMAP_HH */