1 /*
2 * Copyright © 2021 Behdad Esfahbod
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
25 #include "hb.hh"
26 #include "hb-map.hh"
27 #include "hb-set.hh"
28 #include <string>
29
30 int
main(int argc,char ** argv)31 main (int argc, char **argv)
32 {
33
34 /* Test copy constructor. */
35 {
36 hb_map_t v1;
37 v1.set (1, 2);
38 hb_map_t v2 {v1};
39 assert (v1.get_population () == 1);
40 assert (v2.get_population () == 1);
41 assert (v1[1] == 2);
42 assert (v2[1] == 2);
43 }
44
45 /* Test copy assignment. */
46 {
47 hb_map_t v1;
48 v1.set (1, 2);
49 hb_map_t v2 = v1;
50 assert (v1.get_population () == 1);
51 assert (v2.get_population () == 1);
52 assert (v1[1] == 2);
53 assert (v2[1] == 2);
54 }
55
56 /* Test move constructor. */
57 {
58 hb_map_t s {};
59 s.set (1, 2);
60 hb_map_t v (std::move (s));
61 assert (s.get_population () == 0);
62 assert (v.get_population () == 1);
63 }
64
65 /* Test move assignment. */
66 {
67 hb_map_t s {};
68 s.set (1, 2);
69 hb_map_t v;
70 v = std::move (s);
71 assert (s.get_population () == 0);
72 assert (v.get_population () == 1);
73 }
74
75 /* Test initializing from iterable. */
76 {
77 hb_map_t s;
78
79 s.set (1, 2);
80 s.set (3, 4);
81
82 hb_vector_t<hb_codepoint_pair_t> v (s);
83 hb_map_t v0 (v);
84 hb_map_t v1 (s);
85 hb_map_t v2 (std::move (s));
86
87 assert (s.get_population () == 0);
88 assert (v0.get_population () == 2);
89 assert (v1.get_population () == 2);
90 assert (v2.get_population () == 2);
91 }
92
93 /* Test call fini() twice. */
94 {
95 hb_map_t s;
96 for (int i = 0; i < 16; i++)
97 s.set(i, i+1);
98 s.fini();
99 }
100
101 /* Test initializing from iterator. */
102 {
103 hb_map_t s;
104
105 s.set (1, 2);
106 s.set (3, 4);
107
108 hb_map_t v (hb_iter (s));
109
110 assert (v.get_population () == 2);
111 }
112
113 /* Test initializing from initializer list and swapping. */
114 {
115 using pair_t = hb_codepoint_pair_t;
116 hb_map_t v1 {pair_t{1,2}, pair_t{4,5}};
117 hb_map_t v2 {pair_t{3,4}};
118 hb_swap (v1, v2);
119 assert (v1.get_population () == 1);
120 assert (v2.get_population () == 2);
121 }
122
123 /* Test class key / value types. */
124 {
125 hb_hashmap_t<hb_bytes_t, int> m1;
126 hb_hashmap_t<int, hb_bytes_t> m2;
127 hb_hashmap_t<hb_bytes_t, hb_bytes_t> m3;
128 assert (m1.get_population () == 0);
129 assert (m2.get_population () == 0);
130 assert (m3.get_population () == 0);
131 }
132
133 {
134 hb_hashmap_t<int, int> m0;
135 hb_hashmap_t<std::string, int> m1;
136 hb_hashmap_t<int, std::string> m2;
137 hb_hashmap_t<std::string, std::string> m3;
138
139 std::string s;
140 for (unsigned i = 1; i < 1000; i++)
141 {
142 s += "x";
143 m0.set (i, i);
144 m1.set (s, i);
145 m2.set (i, s);
146 m3.set (s, s);
147 }
148 }
149
150 /* Test hashing maps. */
151 {
152 using pair = hb_codepoint_pair_t;
153
154 hb_hashmap_t<hb_map_t, hb_map_t> m1;
155
156 m1.set (hb_map_t (), hb_map_t {});
157 m1.set (hb_map_t (), hb_map_t {pair (1u, 2u)});
158 m1.set (hb_map_t {pair (1u, 2u)}, hb_map_t {pair (2u, 3u)});
159
160 assert (m1.get (hb_map_t ()) == hb_map_t {pair (1u, 2u)});
161 assert (m1.get (hb_map_t {pair (1u, 2u)}) == hb_map_t {pair (2u, 3u)});
162 }
163
164 /* Test hashing sets. */
165 {
166 hb_hashmap_t<hb_set_t, hb_set_t> m1;
167
168 m1.set (hb_set_t (), hb_set_t ());
169 m1.set (hb_set_t (), hb_set_t {1});
170 m1.set (hb_set_t {1, 1000}, hb_set_t {2});
171
172 assert (m1.get (hb_set_t ()) == hb_set_t {1});
173 assert (m1.get (hb_set_t {1000, 1}) == hb_set_t {2});
174 }
175
176 /* Test hashing vectors. */
177 {
178 using vector_t = hb_vector_t<unsigned>;
179
180 hb_hashmap_t<vector_t, vector_t> m1;
181
182 m1.set (vector_t (), vector_t {1});
183 m1.set (vector_t {1}, vector_t {2});
184
185 m1 << hb_pair_t<vector_t, vector_t> {vector_t {2}, vector_t ()};
186
187 assert (m1.get (vector_t ()) == vector_t {1});
188 assert (m1.get (vector_t {1}) == vector_t {2});
189 }
190
191 /* Test moving values */
192 {
193 using vector_t = hb_vector_t<unsigned>;
194
195 hb_hashmap_t<vector_t, vector_t> m1;
196 vector_t v {3};
197 assert (v.length == 1);
198 m1 << hb_pair_t<vector_t, vector_t> {vector_t {3}, v};
199 assert (v.length == 1);
200 m1 << hb_pair_t<vector_t, vector_t&&> {vector_t {4}, std::move (v)};
201 assert (v.length == 0);
202 m1 << hb_pair_t<vector_t&&, vector_t> {vector_t {4}, vector_t {5}};
203 m1 << hb_pair_t<vector_t&&, vector_t&&> {vector_t {4}, vector_t {5}};
204
205 hb_hashmap_t<vector_t, vector_t> m2;
206 vector_t v2 {3};
207 m2.set (vector_t {4}, v2);
208 assert (v2.length == 1);
209 m2.set (vector_t {5}, std::move (v2));
210 assert (v2.length == 0);
211 }
212
213 /* Test hb::shared_ptr. */
214 {
215 hb_hashmap_t<hb::shared_ptr<hb_set_t>, hb::shared_ptr<hb_set_t>> m;
216
217 m.set (hb::shared_ptr<hb_set_t> (hb_set_get_empty ()),
218 hb::shared_ptr<hb_set_t> (hb_set_get_empty ()));
219 m.get (hb::shared_ptr<hb_set_t> (hb_set_get_empty ()));
220 m.iter ();
221 m.keys ();
222 m.values ();
223 m.iter_ref ();
224 m.keys_ref ();
225 m.values_ref ();
226 }
227 /* Test hb::unique_ptr. */
228 {
229 hb_hashmap_t<hb::unique_ptr<hb_set_t>, hb::unique_ptr<hb_set_t>> m;
230
231 m.set (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()),
232 hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
233 m.get (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()));
234 hb::unique_ptr<hb_set_t> *v;
235 m.has (hb::unique_ptr<hb_set_t> (hb_set_get_empty ()), &v);
236 m.iter_ref ();
237 m.keys_ref ();
238 m.values_ref ();
239 }
240 /* Test hashmap with complex shared_ptrs as keys. */
241 {
242 hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> m;
243
244 hb_map_t *m1 = hb_map_create ();
245 hb_map_t *m2 = hb_map_create ();
246 m1->set (1,3);
247 m2->set (1,3);
248
249 hb::shared_ptr<hb_map_t> p1 {m1};
250 hb::shared_ptr<hb_map_t> p2 {m2};
251 m.set (p1,1);
252
253 assert (m.has (p2));
254
255 m1->set (2,4);
256 assert (!m.has (p2));
257 }
258 /* Test value type with hb_bytes_t. */
259 {
260 hb_hashmap_t<int, hb_bytes_t> m;
261 char c_str[] = "Test";
262 hb_bytes_t bytes (c_str);
263
264 m.set (1, bytes);
265 assert (m.has (1));
266 assert (m.get (1) == hb_bytes_t {"Test"});
267 }
268 /* Test operators. */
269 {
270 hb_map_t m1, m2, m3;
271 m1.set (1, 2);
272 m1.set (2, 4);
273 m2.set (1, 2);
274 m2.set (2, 4);
275 m3.set (1, 3);
276 m3.set (3, 5);
277
278 assert (m1 == m2);
279 assert (m1 != m3);
280 assert (!(m2 == m3));
281
282 m2 = m3;
283 assert (m2.has (1));
284 assert (!m2.has (2));
285 assert (m2.has (3));
286
287 assert (m3.has (3));
288 }
289 /* Test reset. */
290 {
291 hb_hashmap_t<int, hb_set_t> m;
292 m.set (1, hb_set_t {1, 2, 3});
293 m.reset ();
294 }
295 /* Test iteration. */
296 {
297 hb_map_t m;
298 m.set (1, 1);
299 m.set (4, 3);
300 m.set (5, 5);
301 m.set (2, 1);
302 m.set (3, 2);
303 m.set (6, 8);
304
305 hb_codepoint_t k;
306 hb_codepoint_t v;
307 unsigned pop = 0;
308 for (signed i = -1;
309 m.next (&i, &k, &v);)
310 {
311 pop++;
312 if (k == 1) assert (v == 1);
313 else if (k == 2) assert (v == 1);
314 else if (k == 3) assert (v == 2);
315 else if (k == 4) assert (v == 3);
316 else if (k == 5) assert (v == 5);
317 else if (k == 6) assert (v == 8);
318 else assert (false);
319 }
320 assert (pop == m.get_population ());
321 }
322 /* Test update */
323 {
324 hb_map_t m1, m2;
325 m1.set (1, 2);
326 m1.set (2, 4);
327 m2.set (1, 3);
328
329 m1.update (m2);
330 assert (m1.get_population () == 2);
331 assert (m1[1] == 3);
332 assert (m1[2] == 4);
333 }
334 /* Test keys / values */
335 {
336 hb_map_t m;
337 m.set (1, 1);
338 m.set (4, 3);
339 m.set (5, 5);
340 m.set (2, 1);
341 m.set (3, 2);
342 m.set (6, 8);
343
344 hb_set_t keys;
345 hb_set_t values;
346
347 hb_copy (m.keys (), keys);
348 hb_copy (m.values (), values);
349
350 assert (keys.is_equal (hb_set_t ({1, 2, 3, 4, 5, 6})));
351 assert (values.is_equal (hb_set_t ({1, 1, 2, 3, 5, 8})));
352
353 assert (keys.is_equal (hb_set_t (m.keys ())));
354 assert (values.is_equal (hb_set_t (m.values ())));
355 }
356
357 return 0;
358 }
359