Line data Source code
1 : /* Vector API for GNU compiler.
2 : Copyright (C) 2004-2026 Free Software Foundation, Inc.
3 : Contributed by Nathan Sidwell <nathan@codesourcery.com>
4 : Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
5 :
6 : This file is part of GCC.
7 :
8 : GCC is free software; you can redistribute it and/or modify it under
9 : the terms of the GNU General Public License as published by the Free
10 : Software Foundation; either version 3, or (at your option) any later
11 : version.
12 :
13 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with GCC; see the file COPYING3. If not see
20 : <http://www.gnu.org/licenses/>. */
21 :
22 : /* This file is compiled twice: once for the generator programs
23 : once for the compiler. */
24 : #ifdef GENERATOR_FILE
25 : #include "bconfig.h"
26 : #else
27 : #include "config.h"
28 : #endif
29 :
30 : #include "system.h"
31 : #include "coretypes.h"
32 : #include "hash-table.h"
33 : #include "selftest.h"
34 : #ifdef GENERATOR_FILE
35 : #include "errors.h"
36 : #else
37 : #include "input.h"
38 : #include "diagnostic-core.h"
39 : #endif
40 :
41 : /* Vector memory usage. */
42 : class vec_usage: public mem_usage
43 : {
44 : public:
45 : /* Default constructor. */
46 0 : vec_usage (): m_items (0), m_items_peak (0), m_element_size (0) {}
47 :
48 : /* Constructor. */
49 0 : vec_usage (size_t allocated, size_t times, size_t peak,
50 : size_t items, size_t items_peak, size_t element_size)
51 0 : : mem_usage (allocated, times, peak),
52 0 : m_items (items), m_items_peak (items_peak),
53 0 : m_element_size (element_size) {}
54 :
55 : /* Sum the usage with SECOND usage. */
56 : vec_usage
57 0 : operator+ (const vec_usage &second)
58 : {
59 0 : return vec_usage (m_allocated + second.m_allocated,
60 0 : m_times + second.m_times,
61 0 : m_peak + second.m_peak,
62 0 : m_items + second.m_items,
63 0 : m_items_peak + second.m_items_peak, 0);
64 : }
65 :
66 : /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
67 : inline void
68 0 : dump (mem_location *loc, mem_usage &total) const
69 : {
70 0 : char s[4096];
71 0 : sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
72 : loc->m_line, loc->m_function);
73 :
74 0 : s[48] = '\0';
75 :
76 0 : fprintf (stderr,
77 : "%-48s %10" PRIu64 PRsa (10) ":%4.1f%%" PRsa (9) "%10" PRIu64
78 : ":%4.1f%%" PRsa (10) PRsa (10) "\n",
79 : s,
80 0 : (uint64_t)m_element_size,
81 0 : SIZE_AMOUNT (m_allocated),
82 0 : m_allocated * 100.0 / total.m_allocated,
83 0 : SIZE_AMOUNT (m_peak), (uint64_t)m_times,
84 0 : m_times * 100.0 / total.m_times,
85 0 : SIZE_AMOUNT (m_items), SIZE_AMOUNT (m_items_peak));
86 0 : }
87 :
88 : /* Dump footer. */
89 : inline void
90 0 : dump_footer ()
91 : {
92 0 : fprintf (stderr, "%s" PRsa (64) PRsa (25) PRsa (16) "\n",
93 0 : "Total", SIZE_AMOUNT (m_allocated),
94 0 : SIZE_AMOUNT (m_times), SIZE_AMOUNT (m_items));
95 0 : }
96 :
97 : /* Dump header with NAME. */
98 : static inline void
99 0 : dump_header (const char *name)
100 : {
101 0 : fprintf (stderr, "%-48s %10s%11s%16s%10s%17s%11s\n", name, "sizeof(T)",
102 : "Leak", "Peak", "Times", "Leak items", "Peak items");
103 0 : }
104 :
105 : /* Current number of items allocated. */
106 : size_t m_items;
107 : /* Peak value of number of allocated items. */
108 : size_t m_items_peak;
109 : /* Size of element of the vector. */
110 : size_t m_element_size;
111 : };
112 :
113 : /* Vector memory description. */
114 : static mem_alloc_description <vec_usage> vec_mem_desc;
115 :
116 : /* Account the overhead. */
117 :
118 : void
119 0 : vec_prefix::register_overhead (void *ptr, size_t elements,
120 : size_t element_size MEM_STAT_DECL)
121 : {
122 0 : vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN, false
123 : FINAL_PASS_MEM_STAT);
124 0 : vec_usage *usage
125 0 : = vec_mem_desc.register_instance_overhead (elements * element_size, ptr);
126 0 : usage->m_element_size = element_size;
127 0 : usage->m_items += elements;
128 0 : if (usage->m_items_peak < usage->m_items)
129 0 : usage->m_items_peak = usage->m_items;
130 0 : }
131 :
132 : /* Notice that the memory allocated for the vector has been freed. */
133 :
134 : void
135 0 : vec_prefix::release_overhead (void *ptr, size_t size, size_t elements,
136 : bool in_dtor MEM_STAT_DECL)
137 : {
138 0 : if (!vec_mem_desc.contains_descriptor_for_instance (ptr))
139 0 : vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN,
140 : false FINAL_PASS_MEM_STAT);
141 0 : vec_usage *usage = vec_mem_desc.release_instance_overhead (ptr, size,
142 : in_dtor);
143 0 : usage->m_items -= elements;
144 0 : }
145 :
146 : /* Calculate the number of slots to reserve a vector, making sure that
147 : it is of at least DESIRED size by growing ALLOC exponentially. */
148 :
149 : unsigned
150 995675770 : vec_prefix::calculate_allocation_1 (unsigned alloc, unsigned desired)
151 : {
152 : /* We must have run out of room. */
153 995675770 : gcc_assert (alloc < desired);
154 :
155 : /* Exponential growth. */
156 995675770 : if (!alloc)
157 : alloc = 4;
158 995675770 : else if (alloc < 16)
159 : /* Double when small. */
160 852343758 : alloc = alloc * 2;
161 : else
162 : /* Grow slower when large. */
163 143332012 : alloc = (alloc * 3 / 2);
164 :
165 : /* If this is still too small, set it to the right size. */
166 995675770 : if (alloc < desired)
167 : alloc = desired;
168 995675770 : return alloc;
169 : }
170 :
171 : /* Dump per-site memory statistics. */
172 :
173 : void
174 0 : dump_vec_loc_statistics (void)
175 : {
176 0 : vec_mem_desc.dump (VEC_ORIGIN);
177 0 : }
178 :
179 : /* Gets the next token from STR delimited by DELIMS (deliminator not included
180 : in returned string).
181 :
182 : Updates STR to be the remaining string after the given token.
183 :
184 : STR and DELIMS must both be valid string_slices.
185 :
186 : If there aren't any of the chars in DELIM in STR (ie no more tokens in STR)
187 : then returns the string, and updates STR to be invalid. */
188 : string_slice
189 630 : string_slice::tokenize (string_slice *str, string_slice delims)
190 : {
191 630 : const char *ptr = str->begin ();
192 :
193 630 : gcc_assert (str->is_valid () && delims.is_valid ());
194 :
195 4976 : for (; ptr < str->end (); ptr++)
196 9036 : for (char c : delims)
197 4690 : if (*ptr == c)
198 : {
199 : /* Update the input string to be the remaining string. */
200 76 : const char *str_begin = str->begin ();
201 76 : *str = string_slice (ptr + 1, str->end ());
202 76 : return string_slice (str_begin, ptr);
203 : }
204 :
205 : /* If no deliminators between the start and end, return the whole string. */
206 554 : string_slice res = *str;
207 554 : *str = string_slice::invalid ();
208 554 : return res;
209 : }
210 :
211 : /* Compares the string_slices STR1 and STR2 giving a lexograpical ordering.
212 : Returns -1 if STR1 comes before STR2, 1 if STR1 comes after, and 0 if the
213 : string_slices have the same contents. */
214 :
215 : int
216 32 : string_slice::strcmp (string_slice str1, string_slice str2)
217 : {
218 56 : for (unsigned int i = 0; i < str1.size () && i < str2.size (); i++)
219 : {
220 32 : if (str1[i] < str2[i])
221 : return -1;
222 28 : if (str1[i] > str2[i])
223 : return 1;
224 : }
225 :
226 24 : if (str1.size () < str2.size ())
227 : return -1;
228 20 : if (str1.size () > str2.size ())
229 8 : return 1;
230 : return 0;
231 : }
232 :
233 : string_slice
234 586 : string_slice::strip ()
235 : {
236 586 : const char *start = this->begin ();
237 586 : const char *end = this->end ();
238 :
239 1236 : while (start < end && ISSPACE (*start))
240 64 : start++;
241 622 : while (end > start && ISSPACE (*(end-1)))
242 36 : end--;
243 :
244 586 : return string_slice (start, end);
245 : }
246 :
247 : #if CHECKING_P
248 : /* Report qsort comparator CMP consistency check failure with P1, P2, P3 as
249 : witness elements. */
250 : ATTRIBUTE_NORETURN ATTRIBUTE_COLD
251 : static void
252 0 : qsort_chk_error (const void *p1, const void *p2, const void *p3,
253 : sort_r_cmp_fn *cmp, void *data)
254 : {
255 0 : if (!p3)
256 : {
257 0 : int r1 = cmp (p1, p2, data), r2 = cmp (p2, p1, data);
258 0 : error ("qsort comparator not anti-symmetric: %d, %d", r1, r2);
259 : }
260 0 : else if (p1 == p2)
261 : {
262 0 : int r = cmp (p1, p3, data);
263 0 : error ("qsort comparator non-negative on sorted output: %d", r);
264 : }
265 : else
266 : {
267 0 : int r1 = cmp (p1, p2, data);
268 0 : int r2 = cmp (p2, p3, data);
269 0 : int r3 = cmp (p1, p3, data);
270 0 : error ("qsort comparator not transitive: %d, %d, %d", r1, r2, r3);
271 : }
272 0 : internal_error ("qsort checking failed");
273 : }
274 :
275 : /* Verify anti-symmetry and transitivity for comparator CMP on sorted array
276 : of N SIZE-sized elements pointed to by BASE. */
277 : void
278 172774936 : qsort_chk (void *base, size_t n, size_t size, sort_r_cmp_fn *cmp, void *data)
279 : {
280 : #if 0
281 : #define LIM(n) (n)
282 : #else
283 : /* Limit overall time complexity to O(n log n). */
284 : #define LIM(n) ((n) <= 16 ? (n) : 12 + floor_log2 (n))
285 : #endif
286 : #define ELT(i) ((const char *) base + (i) * size)
287 : #define CMP(i, j) cmp (ELT (i), ELT (j), data)
288 : #define ERR2(i, j) qsort_chk_error (ELT (i), ELT (j), NULL, cmp, data)
289 : #define ERR3(i, j, k) qsort_chk_error (ELT (i), ELT (j), ELT (k), cmp, data)
290 172774936 : size_t i1, i2, i, j;
291 : /* This outer loop iterates over maximum spans [i1, i2) such that
292 : elements within each span compare equal to each other. */
293 1380632523 : for (i1 = 0; i1 < n; i1 = i2)
294 : {
295 : /* Position i2 one past last element that compares equal to i1'th. */
296 1300027781 : for (i2 = i1 + 1; i2 < n; i2++)
297 1127252845 : if (CMP (i1, i2))
298 : break;
299 92170194 : else if (CMP (i2, i1))
300 0 : ERR2 (i1, i2);
301 1207857587 : size_t lim1 = LIM (i2 - i1), lim2 = LIM (n - i2);
302 : /* Verify that other pairs within current span compare equal. */
303 1289822339 : for (i = i1 + 1; i + 1 < i2; i++)
304 180175293 : for (j = i + 1; j < i1 + lim1; j++)
305 98210541 : if (CMP (i, j))
306 0 : ERR3 (i, i1, j);
307 98210541 : else if (CMP (j, i))
308 0 : ERR2 (i, j);
309 : /* Verify that elements within this span compare less than
310 : elements beyond the span. */
311 2507885368 : for (i = i1; i < i2; i++)
312 13868861997 : for (j = i2; j < i2 + lim2; j++)
313 12568834216 : if (CMP (i, j) >= 0)
314 0 : ERR3 (i, i1, j);
315 12568834216 : else if (CMP (j, i) <= 0)
316 0 : ERR2 (i, j);
317 : }
318 : #undef ERR3
319 : #undef ERR2
320 : #undef CMP
321 : #undef ELT
322 : #undef LIM
323 172774936 : }
324 : #endif /* #if CHECKING_P */
325 :
326 : #ifndef GENERATOR_FILE
327 : #if CHECKING_P
328 :
329 : namespace selftest {
330 :
331 : /* Selftests. */
332 :
333 : /* Call V.safe_push for all ints from START up to, but not including LIMIT.
334 : Helper function for selftests. */
335 :
336 : static void
337 52 : safe_push_range (vec <int>&v, int start, int limit)
338 : {
339 540 : for (int i = start; i < limit; i++)
340 488 : v.safe_push (i);
341 52 : }
342 :
343 : /* Verify forms of initialization. */
344 :
345 : static void
346 4 : test_init ()
347 : {
348 4 : {
349 4 : vec<int> v1{ };
350 4 : ASSERT_EQ (0, v1.length ());
351 :
352 4 : vec<int> v2 (v1);
353 4 : ASSERT_EQ (0, v2.length ());
354 : }
355 :
356 4 : {
357 4 : vec<int> v1 = vec<int>();
358 4 : ASSERT_EQ (0, v1.length ());
359 :
360 4 : vec<int> v2 = v1;
361 4 : ASSERT_EQ (0, v2.length ());
362 : }
363 :
364 4 : {
365 4 : vec<int> v1 (vNULL);
366 4 : ASSERT_EQ (0, v1.length ());
367 4 : v1.safe_push (1);
368 :
369 4 : vec<int> v2 (v1);
370 4 : ASSERT_EQ (1, v1.length ());
371 4 : v2.safe_push (1);
372 :
373 4 : ASSERT_EQ (2, v1.length ());
374 4 : ASSERT_EQ (2, v2.length ());
375 4 : v1.release ();
376 : }
377 4 : }
378 :
379 : /* Verify that vec::quick_push works correctly. */
380 :
381 : static void
382 4 : test_quick_push ()
383 : {
384 4 : auto_vec <int> v;
385 4 : ASSERT_EQ (0, v.length ());
386 4 : v.reserve (3);
387 4 : ASSERT_EQ (0, v.length ());
388 4 : ASSERT_TRUE (v.space (3));
389 4 : v.quick_push (5);
390 4 : v.quick_push (6);
391 4 : v.quick_push (7);
392 4 : ASSERT_EQ (3, v.length ());
393 4 : ASSERT_EQ (5, v[0]);
394 4 : ASSERT_EQ (6, v[1]);
395 4 : ASSERT_EQ (7, v[2]);
396 4 : }
397 :
398 : /* Verify that vec::safe_push works correctly. */
399 :
400 : static void
401 4 : test_safe_push ()
402 : {
403 4 : auto_vec <int> v;
404 4 : ASSERT_EQ (0, v.length ());
405 4 : v.safe_push (5);
406 4 : v.safe_push (6);
407 4 : v.safe_push (7);
408 4 : ASSERT_EQ (3, v.length ());
409 4 : ASSERT_EQ (5, v[0]);
410 4 : ASSERT_EQ (6, v[1]);
411 4 : ASSERT_EQ (7, v[2]);
412 4 : }
413 :
414 : /* Verify that vec::truncate works correctly. */
415 :
416 : static void
417 4 : test_truncate ()
418 : {
419 4 : auto_vec <int> v;
420 4 : ASSERT_EQ (0, v.length ());
421 4 : safe_push_range (v, 0, 10);
422 4 : ASSERT_EQ (10, v.length ());
423 :
424 4 : v.truncate (5);
425 4 : ASSERT_EQ (5, v.length ());
426 4 : }
427 :
428 : /* Verify that vec::safe_grow_cleared works correctly. */
429 :
430 : static void
431 4 : test_safe_grow_cleared ()
432 : {
433 4 : auto_vec <int> v;
434 4 : ASSERT_EQ (0, v.length ());
435 4 : v.safe_grow_cleared (50, true);
436 4 : ASSERT_EQ (50, v.length ());
437 4 : ASSERT_EQ (0, v[0]);
438 4 : ASSERT_EQ (0, v[49]);
439 4 : }
440 :
441 : /* Verify that vec::pop works correctly. */
442 :
443 : static void
444 4 : test_pop ()
445 : {
446 4 : auto_vec <int> v;
447 4 : safe_push_range (v, 5, 20);
448 4 : ASSERT_EQ (15, v.length ());
449 :
450 4 : int last = v.pop ();
451 4 : ASSERT_EQ (19, last);
452 4 : ASSERT_EQ (14, v.length ());
453 4 : }
454 :
455 : /* Verify that vec::safe_insert works correctly. */
456 :
457 : static void
458 4 : test_safe_insert ()
459 : {
460 4 : auto_vec <int> v;
461 4 : safe_push_range (v, 0, 10);
462 4 : v.safe_insert (5, 42);
463 4 : ASSERT_EQ (4, v[4]);
464 4 : ASSERT_EQ (42, v[5]);
465 4 : ASSERT_EQ (5, v[6]);
466 4 : ASSERT_EQ (11, v.length ());
467 4 : }
468 :
469 : /* Verify that vec::ordered_remove works correctly. */
470 :
471 : static void
472 4 : test_ordered_remove ()
473 : {
474 4 : auto_vec <int> v;
475 4 : safe_push_range (v, 0, 10);
476 4 : v.ordered_remove (5);
477 4 : ASSERT_EQ (4, v[4]);
478 4 : ASSERT_EQ (6, v[5]);
479 4 : ASSERT_EQ (9, v.length ());
480 4 : }
481 :
482 : /* Verify that vec::ordered_remove_if works correctly. */
483 :
484 : static void
485 4 : test_ordered_remove_if (void)
486 : {
487 4 : auto_vec <int> v;
488 4 : safe_push_range (v, 0, 10);
489 4 : unsigned ix, ix2;
490 4 : int *elem_ptr;
491 44 : VEC_ORDERED_REMOVE_IF (v, ix, ix2, elem_ptr,
492 4 : *elem_ptr == 5 || *elem_ptr == 7);
493 4 : ASSERT_EQ (4, v[4]);
494 4 : ASSERT_EQ (6, v[5]);
495 4 : ASSERT_EQ (8, v[6]);
496 4 : ASSERT_EQ (8, v.length ());
497 :
498 4 : v.truncate (0);
499 4 : safe_push_range (v, 0, 10);
500 28 : VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 0, 6,
501 4 : *elem_ptr == 5 || *elem_ptr == 7);
502 4 : ASSERT_EQ (4, v[4]);
503 4 : ASSERT_EQ (6, v[5]);
504 4 : ASSERT_EQ (7, v[6]);
505 4 : ASSERT_EQ (9, v.length ());
506 :
507 4 : v.truncate (0);
508 4 : safe_push_range (v, 0, 10);
509 24 : VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 0, 5,
510 4 : *elem_ptr == 5 || *elem_ptr == 7);
511 12 : VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 8, 10,
512 4 : *elem_ptr == 5 || *elem_ptr == 7);
513 4 : ASSERT_EQ (4, v[4]);
514 4 : ASSERT_EQ (5, v[5]);
515 4 : ASSERT_EQ (6, v[6]);
516 4 : ASSERT_EQ (10, v.length ());
517 :
518 4 : v.truncate (0);
519 4 : safe_push_range (v, 0, 10);
520 44 : VEC_ORDERED_REMOVE_IF (v, ix, ix2, elem_ptr, *elem_ptr == 5);
521 4 : ASSERT_EQ (4, v[4]);
522 4 : ASSERT_EQ (6, v[5]);
523 4 : ASSERT_EQ (7, v[6]);
524 4 : ASSERT_EQ (9, v.length ());
525 4 : }
526 :
527 : /* Verify that vec::unordered_remove works correctly. */
528 :
529 : static void
530 4 : test_unordered_remove ()
531 : {
532 4 : auto_vec <int> v;
533 4 : safe_push_range (v, 0, 10);
534 4 : v.unordered_remove (5);
535 4 : ASSERT_EQ (9, v.length ());
536 4 : }
537 :
538 : /* Verify that vec::block_remove works correctly. */
539 :
540 : static void
541 4 : test_block_remove ()
542 : {
543 4 : auto_vec <int> v;
544 4 : safe_push_range (v, 0, 10);
545 4 : v.block_remove (5, 3);
546 4 : ASSERT_EQ (3, v[3]);
547 4 : ASSERT_EQ (4, v[4]);
548 4 : ASSERT_EQ (8, v[5]);
549 4 : ASSERT_EQ (9, v[6]);
550 4 : ASSERT_EQ (7, v.length ());
551 4 : }
552 :
553 : /* Comparator for use by test_qsort. */
554 :
555 : static int
556 492 : reverse_cmp (const void *p_i, const void *p_j)
557 : {
558 492 : return *(const int *)p_j - *(const int *)p_i;
559 : }
560 :
561 : /* Verify that vec::qsort works correctly. */
562 :
563 : static void
564 4 : test_qsort ()
565 : {
566 4 : auto_vec <int> v;
567 4 : safe_push_range (v, 0, 10);
568 4 : v.qsort (reverse_cmp);
569 4 : ASSERT_EQ (9, v[0]);
570 4 : ASSERT_EQ (8, v[1]);
571 4 : ASSERT_EQ (1, v[8]);
572 4 : ASSERT_EQ (0, v[9]);
573 4 : ASSERT_EQ (10, v.length ());
574 4 : }
575 :
576 : /* Verify that vec::reverse works correctly. */
577 :
578 : static void
579 4 : test_reverse ()
580 : {
581 : /* Reversing an empty vec ought to be a no-op. */
582 4 : {
583 4 : auto_vec <int> v;
584 4 : ASSERT_EQ (0, v.length ());
585 4 : v.reverse ();
586 4 : ASSERT_EQ (0, v.length ());
587 4 : }
588 :
589 : /* Verify reversing a vec with even length. */
590 4 : {
591 4 : auto_vec <int> v;
592 4 : safe_push_range (v, 0, 4);
593 4 : v.reverse ();
594 4 : ASSERT_EQ (3, v[0]);
595 4 : ASSERT_EQ (2, v[1]);
596 4 : ASSERT_EQ (1, v[2]);
597 4 : ASSERT_EQ (0, v[3]);
598 4 : ASSERT_EQ (4, v.length ());
599 4 : }
600 :
601 : /* Verify reversing a vec with odd length. */
602 4 : {
603 4 : auto_vec <int> v;
604 4 : safe_push_range (v, 0, 3);
605 4 : v.reverse ();
606 4 : ASSERT_EQ (2, v[0]);
607 4 : ASSERT_EQ (1, v[1]);
608 4 : ASSERT_EQ (0, v[2]);
609 4 : ASSERT_EQ (3, v.length ());
610 4 : }
611 4 : }
612 :
613 : /* A test class that increments a counter every time its dtor is called. */
614 :
615 : class count_dtor
616 : {
617 : public:
618 8 : count_dtor (int *counter) : m_counter (counter) {}
619 8 : ~count_dtor () { (*m_counter)++; }
620 :
621 : private:
622 : int *m_counter;
623 : };
624 :
625 : /* Verify that auto_delete_vec deletes the elements within it. */
626 :
627 : static void
628 4 : test_auto_delete_vec ()
629 : {
630 4 : int dtor_count = 0;
631 4 : {
632 4 : auto_delete_vec <count_dtor> v;
633 4 : v.safe_push (new count_dtor (&dtor_count));
634 4 : v.safe_push (new count_dtor (&dtor_count));
635 4 : }
636 4 : ASSERT_EQ (dtor_count, 2);
637 4 : }
638 :
639 : /* Verify accesses to vector elements are done indirectly. */
640 :
641 : static void
642 4 : test_auto_alias ()
643 : {
644 4 : volatile int i = 1;
645 4 : auto_vec<int, 8> v;
646 4 : v.quick_grow (2);
647 4 : v[0] = 1;
648 4 : v[1] = 2;
649 4 : int val;
650 8 : for (int ix = i; v.iterate (ix, &val); ix++)
651 4 : ASSERT_EQ (val, 2);
652 4 : ASSERT_EQ (val, 0);
653 4 : }
654 :
655 : static void
656 4 : test_string_slice_initializers ()
657 : {
658 4 : string_slice str1 = string_slice ();
659 4 : ASSERT_TRUE (str1.is_valid ());
660 4 : ASSERT_EQ (str1.size (), 0);
661 :
662 4 : string_slice str2 = string_slice ("Test string");
663 4 : ASSERT_TRUE (str2.is_valid ());
664 4 : ASSERT_EQ (str2.size (), 11);
665 :
666 4 : string_slice str3 = "Test string the second";
667 4 : ASSERT_TRUE (str3.is_valid ());
668 4 : ASSERT_EQ (str3.size (), 22);
669 :
670 4 : string_slice str4 = string_slice ("Test string", 4);
671 4 : ASSERT_TRUE (str4.is_valid ());
672 4 : ASSERT_EQ (str4.size (), 4);
673 4 : }
674 :
675 : static void
676 4 : test_string_slice_tokenize ()
677 : {
678 4 : string_slice test_string_slice = "";
679 4 : string_slice test_delims = ",";
680 :
681 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "");
682 8 : ASSERT_FALSE (test_string_slice.is_valid ());
683 :
684 4 : test_string_slice = ",";
685 4 : test_delims = ",";
686 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
687 : string_slice (""));
688 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
689 : string_slice (""));
690 8 : ASSERT_FALSE (test_string_slice.is_valid ());
691 :
692 4 : test_string_slice = ",test.,.test, , test ";
693 4 : test_delims = ",.";
694 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "");
695 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "test");
696 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "");
697 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "");
698 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "test");
699 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), " ");
700 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
701 : " test ");
702 8 : ASSERT_FALSE (test_string_slice.is_valid ());
703 :
704 4 : const char *test_string
705 : = "This is the test string, it \0 is for testing, 123 ,,";
706 4 : test_string_slice = string_slice (test_string, 52);
707 4 : test_delims = string_slice (",\0", 2);
708 :
709 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
710 : "This is the test string");
711 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
712 : " it ");
713 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
714 : " is for testing");
715 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
716 : " 123 ");
717 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
718 : "");
719 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
720 : "");
721 8 : ASSERT_FALSE (test_string_slice.is_valid ());
722 4 : }
723 :
724 : static void
725 4 : test_string_slice_strcmp ()
726 : {
727 4 : ASSERT_EQ (string_slice::strcmp (string_slice (),
728 : string_slice ()), 0);
729 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("test"),
730 : string_slice ()), 1);
731 4 : ASSERT_EQ (string_slice::strcmp (string_slice (),
732 : string_slice ("test")), -1);
733 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("test"),
734 : string_slice ("test")), 0);
735 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("a"),
736 : string_slice ("b")), -1);
737 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("b"),
738 : string_slice ("a")), 1);
739 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("ab", 1),
740 : string_slice ("a")), 0);
741 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("ab", 2),
742 : string_slice ("a")), 1);
743 4 : }
744 :
745 : static void
746 4 : test_string_slice_equality ()
747 : {
748 4 : ASSERT_TRUE (string_slice () == string_slice ());
749 4 : ASSERT_FALSE (string_slice ("test") == string_slice ());
750 4 : ASSERT_FALSE ("test" == string_slice ());
751 4 : ASSERT_FALSE (string_slice () == string_slice ("test"));
752 4 : ASSERT_FALSE (string_slice () == "test");
753 4 : ASSERT_TRUE (string_slice ("test") == string_slice ("test"));
754 4 : ASSERT_TRUE ("test" == string_slice ("test"));
755 4 : ASSERT_TRUE (string_slice ("test") == "test");
756 4 : ASSERT_FALSE (string_slice ("a") == string_slice ("b"));
757 4 : ASSERT_FALSE ("a" == string_slice ("b"));
758 4 : ASSERT_FALSE (string_slice ("a") == "b");
759 4 : ASSERT_FALSE (string_slice ("b") == string_slice ("a"));
760 4 : ASSERT_TRUE (string_slice ("ab", 1) == string_slice ("a"));
761 4 : ASSERT_TRUE (string_slice ("ab", 1) == "a");
762 4 : ASSERT_FALSE (string_slice ("ab", 2) == string_slice ("a"));
763 4 : ASSERT_FALSE (string_slice ("ab", 2) == "a");
764 4 : }
765 :
766 : static void
767 4 : test_string_slice_inequality ()
768 : {
769 4 : ASSERT_FALSE (string_slice () != string_slice ());
770 4 : ASSERT_TRUE (string_slice ("test") != string_slice ());
771 4 : ASSERT_TRUE ("test" != string_slice ());
772 4 : ASSERT_TRUE (string_slice () != string_slice ("test"));
773 4 : ASSERT_TRUE (string_slice () != "test");
774 4 : ASSERT_FALSE (string_slice ("test") != string_slice ("test"));
775 4 : ASSERT_FALSE ("test" != string_slice ("test"));
776 4 : ASSERT_FALSE (string_slice ("test") != "test");
777 4 : ASSERT_TRUE (string_slice ("a") != string_slice ("b"));
778 4 : ASSERT_TRUE ("a" != string_slice ("b"));
779 4 : ASSERT_TRUE (string_slice ("a") != "b");
780 4 : ASSERT_TRUE (string_slice ("b") != string_slice ("a"));
781 4 : ASSERT_FALSE (string_slice ("ab", 1) != string_slice ("a"));
782 4 : ASSERT_FALSE (string_slice ("ab", 1) != "a");
783 4 : ASSERT_TRUE (string_slice ("ab", 2) != string_slice ("a"));
784 4 : ASSERT_TRUE (string_slice ("ab", 2) != "a");
785 4 : }
786 :
787 : static void
788 4 : test_string_slice_invalid ()
789 : {
790 4 : ASSERT_FALSE (string_slice::invalid ().is_valid ());
791 4 : ASSERT_FALSE (string_slice (NULL, 1).is_valid ());
792 4 : ASSERT_TRUE (string_slice (NULL, (size_t) 0).is_valid ());
793 4 : ASSERT_TRUE (string_slice ("Test", (size_t) 0).is_valid ());
794 4 : ASSERT_TRUE (string_slice ().is_valid ());
795 4 : }
796 :
797 : static void
798 4 : test_string_slice_strip ()
799 : {
800 4 : ASSERT_EQ (string_slice (" test ").strip (), string_slice ("test"));
801 4 : ASSERT_EQ (string_slice ("\t test string\t \n ").strip (),
802 : string_slice ("test string"));
803 4 : ASSERT_EQ (string_slice ("test").strip (), string_slice ("test"));
804 4 : ASSERT_EQ (string_slice ().strip (), string_slice ());
805 4 : ASSERT_EQ (string_slice ("\t \n \t ").strip (), string_slice ());
806 4 : }
807 :
808 : /* Run all of the selftests within this file. */
809 :
810 : void
811 4 : vec_cc_tests ()
812 : {
813 4 : test_init ();
814 4 : test_quick_push ();
815 4 : test_safe_push ();
816 4 : test_truncate ();
817 4 : test_safe_grow_cleared ();
818 4 : test_pop ();
819 4 : test_safe_insert ();
820 4 : test_ordered_remove ();
821 4 : test_ordered_remove_if ();
822 4 : test_unordered_remove ();
823 4 : test_block_remove ();
824 4 : test_qsort ();
825 4 : test_reverse ();
826 4 : test_auto_delete_vec ();
827 4 : test_auto_alias ();
828 4 : test_string_slice_initializers ();
829 4 : test_string_slice_tokenize ();
830 4 : test_string_slice_strcmp ();
831 4 : test_string_slice_equality ();
832 4 : test_string_slice_inequality ();
833 4 : test_string_slice_invalid ();
834 4 : test_string_slice_strip ();
835 4 : }
836 :
837 : } // namespace selftest
838 :
839 : #endif /* #if CHECKING_P */
840 : #endif /* #ifndef GENERATOR_FILE */
|