Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.search.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for search, search_n
30#include <cstring> // for strlen
31
32#include <rw_alg_test.h>
33#include <rw_value.h> // for UserClass
34#include <rw_driver.h> // for rw_test()
35
36
39
40// disable explicit instantiation for compilers (like MSVC)
41// that can't handle it
42#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
43
44// instantiate each algorithm on all kinds of iterators
45// it is required to work with (the algorithm may delegate
46// to different implementations specialized for each kind
47// of iterator)
48template
50search (FwdIter<eq_comp<base<> > >,
54
55template
57search (BidirIter<eq_comp<base<> > >,
61
62template
68
69template
71search (FwdIter<eq_comp<base<> > >,
76
77template
79search (BidirIter<eq_comp<base<> > >,
84
85template
92
93template
95search_n (FwdIter<eq_comp<base<> > >,
97 Size<int>, const eq_comp<base<> >&);
98
99template
101search_n (BidirIter<eq_comp<base<> > >,
103 Size<int>, const eq_comp<base<> >&);
104
105template
107search_n (RandomAccessIter<eq_comp<base<> > >,
109 Size<int>, const eq_comp<base<> >&);
110
111template
113search_n (FwdIter<eq_comp<base<> > >,
115 Size<int>, const eq_comp<base<> >&,
117
118template
120search_n (BidirIter<eq_comp<base<> > >,
122 Size<int>, const eq_comp<base<> >&,
124
125template
127search_n (RandomAccessIter<eq_comp<base<> > >,
129 Size<int>, const eq_comp<base<> >&,
131
132#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
133
134} // namespace std
135
136
138template <class T, class U>
140{
141 static std::size_t funcalls_;
142
143 // dummy arguments provided to prevent the class
144 // from being default constructible
145 EqualityPredicate (T* /* dummy */, U* /* dummy */) {
146 funcalls_ = 0;
147 }
148
149 // return a type other than bool but one that is implicitly
150 // convertible to bool to detect incorrect assumptions
151 class ConvertibleToBool {
152 bool result_;
153 public:
154 ConvertibleToBool (bool res): result_ (res) { /* empty */ }
155 operator bool() const { return result_; }
156 };
157
158 ConvertibleToBool operator() (const T &x, const U &y) /* non-const */ {
159 ++funcalls_;
160 return x == y;
161 }
162};
163
164template <class T, class U>
166
167
169// tags to select predicate or non-predicate versions
170template <class T>
172 enum { pred_inx = 1 };
173 int dummy;
174
176};
177
178template <class T>
180 enum { pred_inx = 0 };
181 int dummy;
182
183 // dummy predicate to be used for non-predicate
184 // versions as a placeholder
187
188 bool operator() (const T& , const T& ) {
189 return false;
190 }
191
192 static std::size_t funcalls_;
193 };
194
196};
197
198template <class T>
200
201
202#if defined (_MSC_VER) && _MSC_VER <= 1300
203// to prevent MSVC 7.0 error LNK2001: unresolved external symbol "public:
204// static unsigned int
205// NonPredicateTag<struct UserClass>::DummyPredicate::funcalls_"
207#endif
208
209
211// exercises std::search()
212template
213<class ForwardIterator1, class ForwardIterator2, class T, class PredTag>
214void test_search (int line,
215 const char *seq1, const char *seq2,
216 std::size_t off,
217 ForwardIterator1 it1, ForwardIterator2 it2,
218 const T* , PredTag pred_tag)
219{
220 const char* const fname = "search";
221 static const char* const it1name = type_name (it1, (T*)0);
222 static const char* const it2name = type_name (it2, (T*)0);
223 static const char* const predname =
224 pred_tag.pred_inx ? "BinaryPredicate" : "operator <()";
225
226 const std::size_t nseq1 = std::strlen (seq1);
227 const std::size_t nseq2 = std::strlen (seq2);
228
229 // construct a sequence of `nsrc' elements to pass to search
230 T* const xseq1 = T::from_char (seq1, nseq1);
231 T* const xseq2 = T::from_char (seq2, nseq2);
232
233 // construct iterators pointing to the beginning and end
234 // of the source sequences
235 const ForwardIterator1 first1 =
236 make_iter (xseq1, xseq1, xseq1 + nseq1, it1);
237 const ForwardIterator1 last1 =
238 make_iter (xseq1 + nseq1, xseq1, xseq1 + nseq1, it1);
239
240 const ForwardIterator1 expected = _RWSTD_SIZE_MAX == off ?
241 last1
242 : make_iter (xseq1 + off, xseq1, xseq1 + off, it1);
243
244 _RWSTD_UNUSED (expected);
245
246 const ForwardIterator2 first2 =
247 make_iter (xseq2, xseq2, xseq2 + nseq2, it2);
248 const ForwardIterator2 last2 =
249 make_iter (xseq2 + nseq2, xseq2, xseq2 + nseq2, it2);
250
251 T::n_total_op_eq_ = 0;
252 PredTag::Predicate::funcalls_ = 0;
253
254 typename PredTag::Predicate pred(0, 0);
255
256 const ForwardIterator1 result = pred_tag.pred_inx ?
257 std::search (first1, last1, first2, last2, pred)
258 : std::search (first1, last1, first2, last2);
259
261
262 // 25.1.9, p2:
263 // check the returned iterator
264 rw_assert (result.cur_ == expected.cur_, 0, line,
265 "std::%s<%s, %s%{?}, %s%{;}> (\"%s\", ..., \"%s\") "
266 "found subsequence at %td, expected at %{?}end%{;}%zu%{;}",
267 fname, it1name, it2name, pred_tag.pred_inx, predname,
268 seq1, seq2, result.cur_ - first1.cur_,
269 _RWSTD_SIZE_MAX == off, off);
270
271 // 25.1.9, p3:
272 // Complexity: At most (last1 ­ first1) * (last2 ­ first2)
273 // applications of the corresponding predicate or operator
274 const std::size_t max_op_eq = nseq1 * nseq2;
275 const std::size_t op_called = pred_tag.pred_inx ?
276 PredTag::Predicate::funcalls_
277 : T::n_total_op_eq_;
278
279 rw_assert (op_called <= max_op_eq, 0, line,
280 "std::%s<%s, %s%{?}, %s%{;}> (\"%s\", ..., \"%s\") "
281 "called %s %zu times, expected no more than %zu",
282 fname, it1name, it2name, pred_tag.pred_inx, predname,
283 seq1, seq2, predname, op_called, max_op_eq);
284
285 delete[] xseq1;
286 delete[] xseq2;
287}
288
289template
290<class ForwardIterator1, class ForwardIterator2, class T, class PredTag>
291void test_search (ForwardIterator1 it1, ForwardIterator2 it2,
292 const T* , PredTag pred_tag)
293{
294 static const char* const it1name = type_name (it1, (T*)0);
295 static const char* const it2name = type_name (it2, (T*)0);
296 static const char* const predname = "EqualityPredicate";
297
298 if (pred_tag.pred_inx) { // use predicate
299 rw_info (0, 0, 0,
300 "std::search (%s, %1$s, %s, %2$s, %s)",
301 it1name, it2name, predname);
302 }
303 else { // not use predicate
304 rw_info (0, 0, 0,
305 "std::search (%s, %1$s, %s, %2$s)",
306 it1name, it2name);
307 }
308
309#define TEST(seq1, seq2, off) \
310 test_search (__LINE__, seq1, seq2, std::size_t (off), \
311 it1, it2, (T*)0, pred_tag)
312
313 //
314 // +--------------- sequence to search through
315 // | +---------- subsequence to search for
316 // | | +--- match found at offset
317 // v v v
318 TEST ("", "", 0);
319 TEST ("", "a", -1);
320 TEST ("", "ab", -1);
321 TEST ("", "abc", -1);
322
323 TEST ("a", "ab", -1);
324 TEST ("a", "a", 0);
325 TEST ("ab", "b", 1);
326 TEST ("ab", "bb", -1);
327
328 TEST ("abc", "a", 0);
329 TEST ("abc", "b", 1);
330 TEST ("abc", "c", 2);
331
332 TEST ("abc", "ac", -1);
333 TEST ("abc", "ab", 0);
334 TEST ("abc", "bc", 1);
335 TEST ("abc", "cd", -1);
336 TEST ("abc", "abc", 0);
337
338 TEST ("abcd", "ab", 0);
339 TEST ("abcd", "bc", 1);
340 TEST ("abcd", "cd", 2);
341 TEST ("abcd", "abc", 0);
342 TEST ("abcd", "bcd", 1);
343 TEST ("abcd", "bce", -1);
344
345 TEST ("abcde", "", 0);
346 TEST ("abcde", "a", 0);
347 TEST ("abcde", "b", 1);
348 TEST ("abcde", "c", 2);
349 TEST ("abcde", "d", 3);
350 TEST ("abcde", "e", 4);
351
352 TEST ("abcde", "ab", 0);
353 TEST ("abcde", "bc", 1);
354 TEST ("abcde", "cd", 2);
355 TEST ("abcde", "de", 3);
356 TEST ("abcde", "ef", -1);
357
358 TEST ("abcde", "abc", 0);
359 TEST ("abcde", "bcd", 1);
360 TEST ("abcde", "cde", 2);
361 TEST ("abcde", "def", -1);
362
363 TEST ("abcde", "abcd", 0);
364 TEST ("abcde", "bcde", 1);
365 TEST ("abcde", "cdef", -1);
366
367 TEST ("abcde", "abcde", 0);
368 TEST ("abcde", "bcdef", -1);
369
370 TEST ("abcabfg", "ab", 0);
371 TEST ("abcbcfg", "bc", 1);
372 TEST ("abcdecd", "cd", 2);
373 TEST ("abcdede", "de", 3);
374}
375
376
377
379// exercises std::search_n()
380template <class ForwardIterator, class T, class Size, class PredTag>
381void test_search_n (int line, const char *seq, Size cnt, const char val,
382 std::size_t off, ForwardIterator it,
383 const T* , PredTag pred_tag)
384{
385 const char* const fname = "search_n";
386 static const char* const itname = type_name (it, (T*)0);
387 static const char* const szname = "Size";
388 static const char* const tname = "UserClass";
389 static const char* const predname =
390 pred_tag.pred_inx ? "BinaryPredicate" : "operator <()";
391
392 const std::size_t nseq = std::strlen (seq);
393
394 // construct a sequence of `nsrc' elements to pass to search_n
395 T* const xseq = T::from_char (seq, nseq);
396
397 // construct iterators pointing to the beginning and end
398 // of the source sequence
399 const ForwardIterator first =
400 make_iter (xseq, xseq, xseq + nseq, it);
401 const ForwardIterator last =
402 make_iter (xseq + nseq, xseq, xseq + nseq, it);
403
404 const ForwardIterator expected = _RWSTD_SIZE_MAX == off ?
405 last
406 : make_iter (xseq + off, xseq, xseq + off, it);
407
408 _RWSTD_UNUSED (expected);
409
410 T value;
411 value.data_.val_ = val;
412
413 T::n_total_op_eq_ = 0;
414 PredTag::Predicate::funcalls_ = 0;
415
416 typename PredTag::Predicate pred(0, 0);
417
418 const ForwardIterator result = pred_tag.pred_inx ?
419 std::search_n (first, last, cnt, value, pred)
420 : std::search_n (first, last, cnt, value);
421
423
424 // 25.1.9, p6:
425 // check the returned iterator
426 rw_assert (result.cur_ == expected.cur_, 0, line,
427 "std::%s<%s, %s, %s%{?}, %s%{;}> (\"%s\", ..., %d, '%c') "
428 "found subsequence at %td, expected at %{?}end%{:}%zu%{;}",
429 fname, itname, szname, tname, pred_tag.pred_inx, predname,
430 seq, int (cnt), val, result.cur_ - first.cur_,
431 _RWSTD_SIZE_MAX == off, off);
432
433 // 25.1.9, p7:
434 // Complexity: At most (last ­ first) * count
435 // applications of the corresponding predicate or operator.
436 // In real cases the complexity should be at most (last ­ first)
437 const std::size_t max_op_eq = nseq * cnt;
438 const std::size_t op_called = pred_tag.pred_inx ?
439 PredTag::Predicate::funcalls_
440 : T::n_total_op_eq_;
441
442 rw_assert (op_called <= max_op_eq, 0, line,
443 "std::%s<%s, %s, %s%{?}, %s%{;}> (\"%s\", ..., %d, '%c') "
444 "called %s %zu times, expected no more than %zu",
445 fname, itname, szname, tname, pred_tag.pred_inx, predname,
446 seq, int (cnt), val, predname, op_called, max_op_eq);
447
448 delete[] xseq;
449}
450
451template <class ForwardIterator, class T, class Size, class PredTag>
452void test_search_n (ForwardIterator it, const T* ,
453 const Size* , PredTag pred_tag)
454{
455 static const char* const itname = type_name (it, (T*)0);
456 static const char* const szname = "Size";
457 static const char* const tname = "UserClass";
458 static const char* const predname = "EqualityPredicate";
459
460 if (pred_tag.pred_inx) { // use predicate
461 rw_info (0, 0, 0,
462 "std::search_n (%s, %1$s, %s, const %s&, %s)",
463 itname, szname, tname, predname);
464 }
465 else { // not use predicate
466 rw_info (0, 0, 0,
467 "std::search_n (%s, %1$s, %s, const %s&)",
468 itname, szname, tname);
469 }
470
471#undef TEST
472#define TEST(seq, n, val, off) \
473 test_search_n (__LINE__, seq, Size(n, 0), val, std::size_t (off), \
474 it, (T*)0, pred_tag)
475
476 //
477 // +----------------- sequence to search through
478 // | +------------ number of occurrences
479 // | | +-------- element value to match
480 // | | | +--- match found at offset
481 // v v v v
482 TEST ("", 0, 'x', 0);
483 TEST ("", 1, 'x', -1);
484 TEST ("", 2, 'x', -1);
485 TEST ("", -1, 'x', -1);
486
487 TEST ("A", 0, 'B', 0);
488 TEST ("A", 0, 'A', 0);
489 TEST ("A", 1, 'B', -1);
490 TEST ("A", 1, 'A', 0);
491
492 TEST ("AB", 1, 'A', 0);
493 TEST ("AB", 2, 'A', -1);
494 TEST ("AB", 1, 'B', 1);
495 TEST ("AB", 2, 'B', -1);
496
497 TEST ("ABC", 0, 'A', 0);
498 TEST ("ABC", 0, 'B', 0);
499 TEST ("ABC", 0, 'C', 0);
500 TEST ("ABC", 0, 'D', 0);
501
502 TEST ("ABC", 1, 'A', 0);
503 TEST ("ABC", 1, 'B', 1);
504 TEST ("ABC", 1, 'C', 2);
505 TEST ("ABC", 1, 'D', -1);
506
507 TEST ("ABC", 2, 'A', -1);
508 TEST ("ABC", 2, 'B', -1);
509 TEST ("ABC", 2, 'C', -1);
510 TEST ("ABC", 2, 'D', -1);
511
512 TEST ("ABC", -1, 'A', -1);
513 TEST ("ABC", -2, 'B', -1);
514 TEST ("ABC", -3, 'C', -1);
515 TEST ("ABC", -4, 'D', -1);
516
517 TEST ("ABAD", 1, 'A', 0);
518 TEST ("ABCB", 1, 'B', 1);
519 TEST ("ABCC", 1, 'C', 2);
520
521 TEST ("ABAACAAAD", 2, 'A', 2);
522 TEST ("ABCBBDBBB", 2, 'B', 3);
523
524 TEST ("ABAACAADE", 3, 'A', -1);
525 TEST ("ABCBBDBBE", 3, 'B', -1);
526 TEST ("ABAACAAAD", 3, 'A', 5);
527 TEST ("ABCBBDBBB", 3, 'B', 6);
528}
529
530
532/* extern */ int rw_opt_no_search; // --no-search
533/* extern */ int rw_opt_no_search_n; // --no-search_n
534/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
535/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
536/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
537/* extern */ int rw_opt_no_predicate; // --no-Predicate
538
539
540template <class ForwardIterator, class T, class PredTag>
541void test_search (ForwardIterator it, const T*, PredTag pred_tag)
542{
543 if (rw_opt_no_fwd_iter) {
544 rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
545 }
546 else {
547 test_search (it, FwdIter<T>(), (T*)0, pred_tag);
548 }
549
551 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
552 }
553 else {
554 test_search (it, BidirIter<T>(), (T*)0, pred_tag);
555 }
556
557 if (rw_opt_no_rnd_iter) {
558 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
559 }
560 else {
561 test_search (it, RandomAccessIter<T>(), (T*)0, pred_tag);
562 }
563}
564
565
567template <class T, class PredTag>
568void test_search (const T*, PredTag pred_tag)
569{
570 rw_info (0, 0, 0,
571 "template <class %s, class %1$s%{?}, class %s%{;}> "
572 "std::search (%1$s, %1$s, %1$s, %1$s%{?}, %3$s%{;})",
573 "ForwardIterator", pred_tag.pred_inx, "BinaryPredicate",
574 pred_tag.pred_inx);
575
576 if (rw_opt_no_fwd_iter) {
577 rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
578 }
579 else {
580 test_search (FwdIter<T>(), (T*)0, pred_tag);
581 }
582
584 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
585 }
586 else {
587 test_search (BidirIter<T>(), (T*)0, pred_tag);
588 }
589
590 if (rw_opt_no_rnd_iter) {
591 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
592 }
593 else {
594 test_search (RandomAccessIter<T>(), (T*)0, pred_tag);
595 }
596}
597
598
600template <class T, class Size, class PredTag>
601void test_search_n(const T* , Size* , PredTag pred_tag)
602{
603 rw_info (0, 0, 0,
604 "template <class %s, class %s, class %s%{?}, class %s%{;}> "
605 "std::search_n (%1$s, %1$s, %2$s, %s%{?}, %4$s%{;})",
606 "ForwardIterator", "Size", "T",
607 pred_tag.pred_inx, "BinaryPredicate", "const T&",
608 pred_tag.pred_inx);
609
610 if (rw_opt_no_fwd_iter) {
611 rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
612 }
613 else {
614 test_search_n (FwdIter<T>(), (T*)0, (Size*)0, pred_tag);
615 }
616
618 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
619 }
620 else {
621 test_search_n (BidirIter<T>(), (T*)0, (Size*)0, pred_tag);
622 }
623
624 if (rw_opt_no_rnd_iter) {
625 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
626 }
627 else {
628 test_search_n (RandomAccessIter<T>(), (T*)0, (Size*)0, pred_tag);
629 }
630}
631
632
634template <class T>
635void test_search (const T*)
636{
637 NonPredicateTag<T> non_predicate_tag = { false };
638 PredicateTag<T> predicate_tag = { true };
639
640 test_search ((T*)0, non_predicate_tag);
641
643 rw_note (0, __FILE__, __LINE__, "std::search predicate test disabled");
644 }
645 else {
646 test_search ((T*)0, predicate_tag);
647 }
648}
649
650
652template <class T>
653void test_search_n (const T*)
654{
655 NonPredicateTag<T> non_predicate_tag = { false };
656 PredicateTag<T> predicate_tag = { true };
657
658 test_search_n ((T*)0, (Size<int>*)0, non_predicate_tag);
659
661 rw_note (0, __FILE__, __LINE__,
662 "std::search_n predicate test disabled");
663 }
664 else {
665 test_search_n ((T*)0, (Size<int>*)0, predicate_tag);
666 }
667}
668
669
671static int
672run_test (int, char*[])
673{
674 if (rw_opt_no_search) {
675 rw_note (0, __FILE__, __LINE__, "std::search test disabled");
676 }
677 else {
679 }
680
681 if (rw_opt_no_search_n) {
682 rw_note (0, __FILE__, __LINE__, "std::search_n test disabled");
683 }
684 else {
686 }
687
688 return 0;
689}
690
691
693int main (int argc, char *argv[])
694{
695 return rw_test (argc, argv, __FILE__,
696 "lib.alg.search",
697 0 /* no comment */, run_test,
698 "|-no-search# "
699 "|-no-search_n# "
700 "|-no-ForwardIterator# "
701 "|-no-BidirectionalIterator# "
702 "|-no-RandomAccessIterator# "
703 "|-no-Predicate",
710}
#define T
Definition 17.names.cpp:163
#define y
Definition 17.names.cpp:141
#define cnt
Definition 17.names.cpp:459
#define line
Definition 17.names.cpp:490
#define res
Definition 17.names.cpp:531
#define last
Definition 17.names.cpp:487
#define x
Definition 17.names.cpp:140
#define off
Definition 17.names.cpp:507
#define val
Definition 17.names.cpp:570
#define ForwardIterator
Definition 17.names.cpp:469
#define U
Definition 17.names.cpp:164
volatile int result
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define TEST(seq1, seq2, off)
void test_search_n(int line, const char *seq, Size cnt, const char val, std::size_t off, ForwardIterator it, const T *, PredTag pred_tag)
int rw_opt_no_fwd_iter
int rw_opt_no_rnd_iter
int rw_opt_no_search
int rw_opt_no_bidir_iter
int rw_opt_no_predicate
int rw_opt_no_search_n
void test_search(int line, const char *seq1, const char *seq2, std::size_t off, ForwardIterator1 it1, ForwardIterator2 it2, const T *, PredTag pred_tag)
T value(const T &val)
const char * type_name()
#define main
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
Definition json.h:5363
T * make_iter(T *cur, const T *, const T *, T *)
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_note(int, const char *, int, const char *,...)
Definition driver.cpp:1664
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
#define bool
Definition stdbool.h:24
ConvertibleToBool operator()(const T &x, const U &y)
EqualityPredicate(T *, U *)
static std::size_t funcalls_
bool operator()(const T &, const T &)
DummyPredicate Predicate
EqualityPredicate< T, T > Predicate