position_iterator_tests.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. /*=============================================================================
  2. Copyright (c) 2003 Giovanni Bajo
  3. http://spirit.sourceforge.net/
  4. Use, modification and distribution is subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #include <boost/detail/lightweight_test.hpp>
  9. #include <iostream>
  10. #include <vector>
  11. #include <string>
  12. #include <list>
  13. #include <algorithm>
  14. #include <iterator>
  15. #include <cstddef>
  16. #include <boost/config.hpp>
  17. #include <boost/concept_check.hpp>
  18. #include <boost/mpl/if.hpp>
  19. #include <boost/mpl/list.hpp>
  20. #include <boost/mpl/for_each.hpp>
  21. // Our baby
  22. #include <boost/spirit/include/classic_position_iterator.hpp>
  23. using namespace std;
  24. using namespace BOOST_SPIRIT_CLASSIC_NS;
  25. namespace mpl = boost::mpl;
  26. ///////////////////////////////////////////////////////////////////////////////
  27. namespace test_impl {
  28. template <typename IterT>
  29. void InstanciateTestOne(void)
  30. {
  31. IterT();
  32. // Check that the iterator is a full non-mutable forward iterator
  33. typedef boost::ForwardIteratorConcept<IterT> concept_t;
  34. boost::function_requires<concept_t>();
  35. }
  36. struct InstanciateTest
  37. {
  38. template <typename BaseIterT>
  39. void operator()(BaseIterT )
  40. {
  41. InstanciateTestOne<position_iterator<BaseIterT> >();
  42. InstanciateTestOne<position_iterator2<BaseIterT> >();
  43. InstanciateTestOne<position_iterator<BaseIterT, file_position_without_column> >();
  44. InstanciateTestOne<position_iterator2<BaseIterT, file_position_without_column> >();
  45. }
  46. };
  47. ///////////////////////////////////////////////////////////////////////////////
  48. } /* namespace test_impl */
  49. // These tests are defined after main() to be absolutely sure that the
  50. // instantiation test will happen before any other (since it's mainly
  51. // a compile-time test).
  52. void CheckInstantiation(void);
  53. void CheckConstructors(void);
  54. void CheckBasicFunctionality(void);
  55. void CheckColumnCounting(void);
  56. void CheckLineExtraction(void);
  57. void CheckDistance(void);
  58. void CheckSingular();
  59. void CheckInstantiation(void)
  60. {
  61. typedef mpl::list
  62. <
  63. char*
  64. ,const char*
  65. ,string::iterator
  66. ,string::const_iterator
  67. > iter_list_t;
  68. mpl::for_each<iter_list_t>(test_impl::InstanciateTest());
  69. }
  70. int main(void)
  71. {
  72. CheckInstantiation();
  73. CheckConstructors();
  74. CheckBasicFunctionality();
  75. CheckColumnCounting();
  76. CheckLineExtraction();
  77. CheckDistance();
  78. CheckSingular();
  79. return boost::report_errors();
  80. }
  81. ///////////////////////////////////////////////////////////////////////////////
  82. namespace test_impl {
  83. template <typename IterT>
  84. void CheckIncrement(IterT iter)
  85. {
  86. IterT end;
  87. // Check also that copy construction and assignment do not
  88. // interfere with increment
  89. IterT iter2(iter);
  90. IterT iter3 = iter;
  91. BOOST_TEST(iter != end);
  92. BOOST_TEST(iter2 != end);
  93. BOOST_TEST(iter3 != end);
  94. BOOST_TEST(*iter == '0');
  95. ++iter;
  96. ++iter2;
  97. ++iter3;
  98. BOOST_TEST(iter == iter2);
  99. BOOST_TEST(iter == iter3);
  100. BOOST_TEST(*iter == *iter2);
  101. BOOST_TEST(*iter == *iter3);
  102. BOOST_TEST(iter.get_position() == iter2.get_position());
  103. BOOST_TEST(iter.get_position() == iter3.get_position());
  104. BOOST_TEST(*iter == '1');
  105. BOOST_TEST(*iter++ == '1');
  106. BOOST_TEST(*iter2++ == '1');
  107. BOOST_TEST(*iter3++ == '1');
  108. BOOST_TEST(*iter == *iter2);
  109. BOOST_TEST(*iter == *iter3);
  110. BOOST_TEST(iter.get_position() == iter2.get_position());
  111. BOOST_TEST(iter.get_position() == iter3.get_position());
  112. BOOST_TEST(*iter == '2');
  113. ++iter; ++iter; ++iter; ++iter; ++iter; ++iter; ++iter;
  114. BOOST_TEST(*iter == '9');
  115. ++iter;
  116. BOOST_TEST(iter == end);
  117. // Check that one after end is no more end
  118. ++iter;
  119. BOOST_TEST(iter != end);
  120. }
  121. template <typename IterT>
  122. void CheckLineCounting(IterT iter)
  123. {
  124. IterT end;
  125. BOOST_TEST(*iter == '\n');
  126. BOOST_TEST(iter.get_position().line == 1);
  127. ++iter; // 0
  128. BOOST_TEST(iter.get_position().line == 2);
  129. ++iter; // 1
  130. ++iter; // 2
  131. ++iter; // 3
  132. ++iter; // \r
  133. BOOST_TEST(*iter == '\r');
  134. BOOST_TEST(iter.get_position().line == 2);
  135. ++iter; // \n
  136. BOOST_TEST(*iter == '\n');
  137. BOOST_TEST(iter.get_position().line == 2);
  138. ++iter; // 4
  139. BOOST_TEST(iter.get_position().line == 3);
  140. ++iter; // 5
  141. ++iter; // 6
  142. ++iter; // 7
  143. ++iter; // \n
  144. BOOST_TEST(*iter == '\n');
  145. BOOST_TEST(iter.get_position().line == 3);
  146. ++iter; // 8
  147. BOOST_TEST(iter.get_position().line == 4);
  148. ++iter; // 9
  149. ++iter; // \n
  150. BOOST_TEST(iter.get_position().line == 4);
  151. BOOST_TEST(*iter == '\n');
  152. ++iter; // \r
  153. BOOST_TEST(iter.get_position().line == 5);
  154. BOOST_TEST(*iter == '\r');
  155. ++iter; // end
  156. BOOST_TEST(iter.get_position().line == 6);
  157. BOOST_TEST(iter == end);
  158. }
  159. template <typename IterT>
  160. void CheckColumnCounting_Tab4(IterT iter)
  161. {
  162. IterT end;
  163. // Don't call set_tabchars() here because
  164. // default must be 3.
  165. BOOST_TEST(*iter == '\t');
  166. BOOST_TEST(iter.get_position().column == 1);
  167. ++iter; // 0
  168. BOOST_TEST(iter.get_position().column == 5);
  169. ++iter; // 1
  170. BOOST_TEST(iter.get_position().column == 6);
  171. ++iter; // 2
  172. BOOST_TEST(iter.get_position().column == 7);
  173. ++iter; // 3
  174. BOOST_TEST(iter.get_position().column == 8);
  175. ++iter; // tab
  176. BOOST_TEST(*iter == '\t');
  177. BOOST_TEST(iter.get_position().column == 9);
  178. ++iter; // 4
  179. BOOST_TEST(iter.get_position().column == 13);
  180. ++iter; // tab
  181. BOOST_TEST(*iter == '\t');
  182. BOOST_TEST(iter.get_position().column == 14);
  183. ++iter; // 5
  184. BOOST_TEST(iter.get_position().column == 17);
  185. ++iter; // tab
  186. BOOST_TEST(*iter == '\t');
  187. BOOST_TEST(iter.get_position().column == 18);
  188. ++iter; // end
  189. BOOST_TEST(iter == end);
  190. }
  191. template <typename IterT>
  192. void CheckColumnCounting_Tab3(IterT iter)
  193. {
  194. IterT end;
  195. iter.set_tabchars(3);
  196. // Check also that tab settings propagates through
  197. // assignment and copy construction
  198. IterT iter2(iter);
  199. IterT iter3; iter3 = iter2;
  200. BOOST_TEST(*iter == '\t');
  201. BOOST_TEST(iter.get_position().column == 1);
  202. ++iter; // 0
  203. ++iter2; ++iter3;
  204. BOOST_TEST(iter.get_position().column == 4);
  205. BOOST_TEST(iter2.get_position().column == 4);
  206. BOOST_TEST(iter3.get_position().column == 4);
  207. ++iter; // 1
  208. BOOST_TEST(iter.get_position().column == 5);
  209. ++iter; // 2
  210. BOOST_TEST(iter.get_position().column == 6);
  211. ++iter; // 3
  212. BOOST_TEST(iter.get_position().column == 7);
  213. ++iter; // tab
  214. BOOST_TEST(*iter == '\t');
  215. BOOST_TEST(iter.get_position().column == 8);
  216. ++iter; // 4
  217. BOOST_TEST(iter.get_position().column == 10);
  218. ++iter; // tab
  219. BOOST_TEST(*iter == '\t');
  220. BOOST_TEST(iter.get_position().column == 11);
  221. ++iter; // 5
  222. BOOST_TEST(iter.get_position().column == 13);
  223. ++iter; // tab
  224. BOOST_TEST(*iter == '\t');
  225. BOOST_TEST(iter.get_position().column == 14);
  226. ++iter; // end
  227. BOOST_TEST(iter == end);
  228. }
  229. const string line1 = "abcd";
  230. const string line2 = "efgh";
  231. const string linebuf = "\n" + line1 + "\n" + line2 + "\n";
  232. template <typename IterT>
  233. void AssertIterString(IterT begin, IterT end, string s)
  234. {
  235. BOOST_TEST(string(begin, end) == s);
  236. }
  237. template <typename IterT>
  238. void CheckLineExtractionOne(IterT iter)
  239. {
  240. IterT end;
  241. // At the start, we are on a newline, which is an empty
  242. // string
  243. BOOST_TEST(iter.get_currentline() == string());
  244. BOOST_TEST(
  245. string(iter.get_currentline_begin(), iter.get_currentline_end())
  246. == string());
  247. ++iter; // a
  248. ++iter; // b
  249. ++iter; // c
  250. BOOST_TEST(iter.get_currentline() == line1);
  251. AssertIterString(
  252. iter.get_currentline_begin(),
  253. iter.get_currentline_end(),
  254. line1);
  255. ++iter; // d
  256. ++iter; // newline
  257. ++iter; // e
  258. // check that copy construction and assignment do
  259. // not interfere with get_currentline
  260. IterT iter2(iter);
  261. IterT iter3; iter3 = iter;
  262. BOOST_TEST(iter2.get_currentline() == line2);
  263. BOOST_TEST(iter3.get_currentline() == line2);
  264. AssertIterString(
  265. iter2.get_currentline_begin(),
  266. iter2.get_currentline_end(),
  267. line2);
  268. AssertIterString(
  269. iter3.get_currentline_begin(),
  270. iter3.get_currentline_end(),
  271. line2);
  272. ++iter; // f
  273. ++iter; // g
  274. ++iter; // h
  275. ++iter; // newline
  276. // Check when the iterator is on a newline
  277. BOOST_TEST(iter.get_currentline() == line2);
  278. AssertIterString(
  279. iter.get_currentline_begin(),
  280. iter.get_currentline_end(),
  281. line2);
  282. ++iter;
  283. BOOST_TEST(iter == end);
  284. }
  285. void CheckLineExtraction(void)
  286. {
  287. typedef string::const_iterator iter_t;
  288. CheckLineExtractionOne(
  289. position_iterator2<iter_t, file_position>
  290. (linebuf.begin(), linebuf.end(), ""));
  291. CheckLineExtractionOne(
  292. position_iterator2<iter_t, file_position_without_column>
  293. (linebuf.begin(), linebuf.end(), ""));
  294. }
  295. template <typename IterT>
  296. void CheckEmptySequence(void)
  297. {
  298. typedef IterT iter_t;
  299. char a[10];
  300. // Check construction with empty sequence, and
  301. // correct propagation of the information
  302. iter_t iter(a,a, "");
  303. iter_t iter2(iter);
  304. iter_t iter3; iter3 = iter;
  305. BOOST_TEST(iter == iter_t());
  306. BOOST_TEST(iter2 == iter_t());
  307. BOOST_TEST(iter3 == iter_t());
  308. }
  309. template <typename IterC, typename Iter>
  310. void CheckConstructors(void)
  311. {
  312. char a[20];
  313. std::string name = "abc";
  314. file_position_without_column pos(name,1);
  315. file_position posc(name,1,1);
  316. typedef IterC iterc_t;
  317. typedef Iter iter_t;
  318. BOOST_TEST(iterc_t(a,a+20,name).get_position() == posc);
  319. BOOST_TEST(iterc_t(a,a+20,name,1).get_position() == posc);
  320. BOOST_TEST(iterc_t(a,a+20,name,1,1).get_position() == posc);
  321. BOOST_TEST(iterc_t(a,a+20,posc).get_position() == posc);
  322. BOOST_TEST(iter_t(a,a+20,name).get_position() == pos);
  323. BOOST_TEST(iter_t(a,a+20,name,1).get_position() == pos);
  324. BOOST_TEST(iter_t(a,a+20,pos).get_position() == pos);
  325. // Check copy constructor and assignment. Notice that we want
  326. // an implicit copy constructor.
  327. iterc_t ic1(a,a+20,name);
  328. iterc_t ic2 = ic1;
  329. iterc_t ic3; ic3 = ic1;
  330. BOOST_TEST(ic1 == ic2);
  331. BOOST_TEST(ic1 == ic3);
  332. BOOST_TEST(ic1.get_position() == ic2.get_position());
  333. BOOST_TEST(ic1.get_position() == ic3.get_position());
  334. iter_t i1(a,a+20,name);
  335. iter_t i2 = i1;
  336. iter_t i3; i3 = i1;
  337. BOOST_TEST(i1 == i2);
  338. BOOST_TEST(i1 == i3);
  339. BOOST_TEST(i1.get_position() == i2.get_position());
  340. BOOST_TEST(i1.get_position() == i3.get_position());
  341. // Check construction with an empty sequence
  342. CheckEmptySequence<iter_t>();
  343. CheckEmptySequence<iterc_t>();
  344. }
  345. template <typename IterT>
  346. void CheckDistance(IterT begin)
  347. {
  348. IterT end;
  349. std::size_t std_distance = std::distance(begin, end);
  350. std::size_t manual_count = 0;
  351. for(IterT it = begin; it != end; ++it)
  352. ++manual_count;
  353. BOOST_TEST(std_distance == manual_count);
  354. }
  355. ///////////////////////////////////////////////////////////////////////////////
  356. } /* namespace test_impl */
  357. void CheckConstructors(void)
  358. {
  359. test_impl::CheckConstructors
  360. <
  361. position_iterator<char*, file_position>,
  362. position_iterator<char*, file_position_without_column>
  363. >();
  364. test_impl::CheckConstructors
  365. <
  366. position_iterator2<char*, file_position>,
  367. position_iterator2<char*, file_position_without_column>
  368. >();
  369. }
  370. void CheckBasicFunctionality(void)
  371. {
  372. const char* a = "0123456789";
  373. typedef const char* iter_t;
  374. test_impl::CheckIncrement(position_iterator<iter_t>(a, a+10, ""));
  375. test_impl::CheckIncrement(position_iterator2<iter_t>(a, a+10, ""));
  376. test_impl::CheckIncrement(position_iterator<iter_t, file_position_without_column>(a, a+10, ""));
  377. test_impl::CheckIncrement(position_iterator2<iter_t, file_position_without_column>(a, a+10, ""));
  378. const char* b = "\n0123\r\n4567\n89\n\r";
  379. test_impl::CheckLineCounting(position_iterator<iter_t>(b, b+16, ""));
  380. test_impl::CheckLineCounting(position_iterator2<iter_t>(b, b+16, ""));
  381. test_impl::CheckLineCounting(position_iterator<iter_t, file_position_without_column>(b, b+16, ""));
  382. test_impl::CheckLineCounting(position_iterator2<iter_t, file_position_without_column>(b, b+16, ""));
  383. }
  384. void CheckColumnCounting(void)
  385. {
  386. const char* a = "\t0123\t4\t5\t";
  387. typedef const char* iter_t;
  388. test_impl::CheckColumnCounting_Tab4(position_iterator<iter_t>(a, a+10, ""));
  389. test_impl::CheckColumnCounting_Tab4(position_iterator2<iter_t>(a, a+10, ""));
  390. test_impl::CheckColumnCounting_Tab3(position_iterator<iter_t>(a, a+10, ""));
  391. test_impl::CheckColumnCounting_Tab3(position_iterator2<iter_t>(a, a+10, ""));
  392. }
  393. void CheckLineExtraction(void)
  394. {
  395. test_impl::CheckLineExtraction();
  396. }
  397. void CheckDistance(void)
  398. {
  399. const char* b = "\n0123\r\n4567\n89\n\r";
  400. typedef const char* iter_t;
  401. test_impl::CheckDistance(position_iterator<iter_t>(b, b+15, ""));
  402. test_impl::CheckDistance(position_iterator2<iter_t>(b, b+15, ""));
  403. test_impl::CheckDistance(position_iterator<iter_t, file_position_without_column>(b, b+15, ""));
  404. test_impl::CheckDistance(position_iterator2<iter_t, file_position_without_column>(b, b+15, ""));
  405. }
  406. ///////////////////////////////////////////////////////////////////////////////
  407. namespace test_impl {
  408. template <bool AsValue = false>
  409. class check_singular_iterator
  410. {
  411. bool singular_;
  412. int count_;
  413. public:
  414. typedef std::forward_iterator_tag iterator_category;
  415. typedef int value_type;
  416. typedef std::ptrdiff_t difference_type;
  417. typedef int const* pointer;
  418. typedef typename boost::mpl::if_c<AsValue, int, int const&>::type reference;
  419. check_singular_iterator() : singular_(true), count_(0) {}
  420. explicit check_singular_iterator(int x) : singular_(false), count_(x) {}
  421. reference operator*() const {
  422. BOOST_TEST(!singular_);
  423. return count_;
  424. }
  425. pointer operator->() const {
  426. BOOST_TEST(!singular_);
  427. return &count_;
  428. }
  429. check_singular_iterator& operator++() {
  430. BOOST_TEST(count_ > 0);
  431. --count_;
  432. return *this;
  433. }
  434. check_singular_iterator operator++(int) {
  435. check_singular_iterator tmp(*this);
  436. ++(*this);
  437. return tmp;
  438. }
  439. bool operator==(check_singular_iterator const& other) const {
  440. BOOST_TEST(!singular_ && !other.singular_);
  441. return count_ == other.count_;
  442. }
  443. bool operator!=(check_singular_iterator const& other) const {
  444. return !(*this == other);
  445. }
  446. };
  447. template <typename CountIterator, typename Iterator>
  448. void CheckSingularImpl()
  449. {
  450. CountIterator begin(Iterator(5), Iterator(0));
  451. CountIterator end1(Iterator(0), Iterator(0));
  452. CountIterator end2;
  453. BOOST_TEST(begin == begin);
  454. BOOST_TEST(begin != end1);
  455. BOOST_TEST(begin != end2);
  456. BOOST_TEST(end1 != begin);
  457. BOOST_TEST(end1 == end1);
  458. BOOST_TEST(end1 == end2);
  459. BOOST_TEST(end2 != begin);
  460. BOOST_TEST(end2 == end1);
  461. BOOST_TEST(end2 == end2);
  462. BOOST_TEST(std::distance(begin, begin) == 0);
  463. BOOST_TEST(std::distance(begin, end1) == 5);
  464. BOOST_TEST(std::distance(begin, end2) == 5);
  465. BOOST_TEST(std::distance(end1, end1) == 0);
  466. BOOST_TEST(std::distance(end1, end2) == 0);
  467. BOOST_TEST(std::distance(end2, end1) == 0);
  468. BOOST_TEST(std::distance(end2, end2) == 0);
  469. BOOST_TEST(*begin == 5);
  470. }
  471. template <typename PositionT>
  472. void CheckSingular()
  473. {
  474. {
  475. typedef check_singular_iterator<false> interator_type;
  476. CheckSingularImpl<position_iterator<interator_type, PositionT>, interator_type>();
  477. CheckSingularImpl<position_iterator2<interator_type, PositionT>, interator_type>();
  478. }
  479. {
  480. typedef check_singular_iterator<true> interator_type;
  481. CheckSingularImpl<position_iterator<interator_type, PositionT>, interator_type>();
  482. CheckSingularImpl<position_iterator2<interator_type, PositionT>, interator_type>();
  483. }
  484. }
  485. }
  486. void CheckSingular()
  487. {
  488. test_impl::CheckSingular<file_position>();
  489. test_impl::CheckSingular<file_position_without_column>();
  490. }