basic_cstring.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. // (C) Copyright Gennadiy Rozental 2001.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/test for the library home page.
  6. //
  7. // File : $RCSfile$
  8. //
  9. // Version : $Revision$
  10. //
  11. // Description : class basic_cstring wraps C string and provide std_string like
  12. // interface
  13. // ***************************************************************************
  14. #ifndef BOOST_TEST_UTILS_BASIC_CSTRING_HPP
  15. #define BOOST_TEST_UTILS_BASIC_CSTRING_HPP
  16. // Boost.Test
  17. #include <boost/test/utils/basic_cstring/basic_cstring_fwd.hpp>
  18. #include <boost/test/utils/basic_cstring/bcs_char_traits.hpp>
  19. // Boost
  20. #include <boost/type_traits/remove_cv.hpp>
  21. // STL
  22. #include <string>
  23. #if defined(BOOST_TEST_STRING_VIEW)
  24. #include <string_view>
  25. #endif
  26. #include <boost/test/detail/suppress_warnings.hpp>
  27. //____________________________________________________________________________//
  28. namespace boost {
  29. namespace unit_test {
  30. // ************************************************************************** //
  31. // ************** basic_cstring ************** //
  32. // ************************************************************************** //
  33. template<typename CharT>
  34. class BOOST_SYMBOL_VISIBLE basic_cstring {
  35. typedef basic_cstring<CharT> self_type;
  36. public:
  37. // Subtypes
  38. typedef ut_detail::bcs_char_traits<CharT> traits_type;
  39. typedef typename traits_type::std_string std_string;
  40. typedef CharT value_type;
  41. typedef typename remove_cv<value_type>::type value_ret_type;
  42. typedef value_type* pointer;
  43. typedef value_type const* const_pointer;
  44. typedef value_type& reference;
  45. typedef const value_type& const_reference;
  46. typedef std::size_t size_type;
  47. typedef std::ptrdiff_t difference_type;
  48. typedef value_type const* const_iterator;
  49. typedef value_type* iterator;
  50. // !! should also present reverse_iterator, const_reverse_iterator
  51. #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) && !defined(__DCC__)
  52. BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
  53. #else
  54. // IBM/VisualAge version 6 is not able to handle enums larger than 4 bytes.
  55. // But size_type is 8 bytes in 64bit mode.
  56. static const size_type npos = -1 ;
  57. #endif
  58. static pointer null_str();
  59. // Constructors; default copy constructor is generated by compiler
  60. basic_cstring();
  61. basic_cstring( basic_cstring const & );
  62. basic_cstring( std_string const& s );
  63. basic_cstring( pointer s );
  64. template<typename LenType>
  65. basic_cstring( pointer s, LenType len ) : m_begin( s ), m_end( m_begin + len ) {}
  66. basic_cstring( pointer first, pointer last );
  67. // data access methods
  68. value_ret_type operator[]( size_type index ) const;
  69. value_ret_type at( size_type index ) const;
  70. // size operators
  71. size_type size() const;
  72. bool is_empty() const;
  73. void clear();
  74. void resize( size_type new_len );
  75. // !! only for STL container conformance use is_empty instead
  76. bool empty() const;
  77. // Trimming
  78. self_type& trim_right( size_type trim_size );
  79. self_type& trim_left( size_type trim_size );
  80. self_type& trim_right( iterator it );
  81. self_type& trim_left( iterator it );
  82. #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(800))
  83. self_type& trim_left( self_type exclusions = self_type() ) ;
  84. self_type& trim_right( self_type exclusions = self_type() ) ;
  85. self_type& trim( self_type exclusions = self_type() ) ;
  86. #else
  87. // VA C++/XL C++ v6 and v8 has in this case a problem with the default arguments.
  88. self_type& trim_left( self_type exclusions );
  89. self_type& trim_right( self_type exclusions );
  90. self_type& trim( self_type exclusions );
  91. self_type& trim_left() { return trim_left( self_type() ); }
  92. self_type& trim_right() { return trim_right( self_type() ); }
  93. self_type& trim() { return trim( self_type() ); }
  94. #endif
  95. // Assignment operators
  96. basic_cstring& operator=( self_type const& s );
  97. basic_cstring& operator=( std_string const& s );
  98. basic_cstring& operator=( pointer s );
  99. template<typename CharT2>
  100. basic_cstring& assign( basic_cstring<CharT2> const& s )
  101. {
  102. return *this = basic_cstring<CharT>( s.begin(), s.end() );
  103. }
  104. template<typename PosType, typename LenType>
  105. basic_cstring& assign( self_type const& s, PosType pos, LenType len )
  106. {
  107. return *this = self_type( s.m_begin + pos, len );
  108. }
  109. basic_cstring& assign( std_string const& s );
  110. template<typename PosType, typename LenType>
  111. basic_cstring& assign( std_string const& s, PosType pos, LenType len )
  112. {
  113. return *this = self_type( s.c_str() + pos, len );
  114. }
  115. basic_cstring& assign( pointer s );
  116. template<typename LenType>
  117. basic_cstring& assign( pointer s, LenType len )
  118. {
  119. return *this = self_type( s, len );
  120. }
  121. basic_cstring& assign( pointer f, pointer l );
  122. // swapping
  123. void swap( self_type& s );
  124. // Iterators
  125. iterator begin();
  126. const_iterator begin() const;
  127. iterator end();
  128. const_iterator end() const;
  129. // !! should have rbegin, rend
  130. // substring search operation
  131. size_type find( basic_cstring ) const;
  132. size_type rfind( basic_cstring ) const;
  133. self_type substr( size_type beg_index, size_type end_index = npos ) const;
  134. private:
  135. static self_type default_trim_ex();
  136. // Data members
  137. iterator m_begin;
  138. iterator m_end;
  139. static CharT null;
  140. };
  141. // ************************************************************************** //
  142. // ************** cstring_string_view_helper ************** //
  143. // ************************************************************************** //
  144. #if defined(BOOST_TEST_STRING_VIEW)
  145. // Helper for instanciating a subclass of cstring using a string_view. We do not
  146. // change the API of cstring using BOOST_TEST_STRING_VIEW as the code should remain
  147. // compatible between boost.test and test module using different compiler options.
  148. //! @internal
  149. template <class CharT, class string_view_t = std::basic_string_view<CharT>>
  150. class BOOST_SYMBOL_VISIBLE stringview_cstring_helper : public basic_cstring<CharT> {
  151. public:
  152. stringview_cstring_helper(string_view_t const& sv)
  153. : basic_cstring<CharT>(const_cast<CharT*>(sv.data()), sv.size())
  154. {}
  155. };
  156. #endif
  157. // ************************************************************************** //
  158. // ************** basic_cstring::impl ************** //
  159. // ************************************************************************** //
  160. //____________________________________________________________________________//
  161. template<typename CharT>
  162. CharT basic_cstring<CharT>::null = 0;
  163. //____________________________________________________________________________//
  164. template<typename CharT>
  165. inline typename basic_cstring<CharT>::pointer
  166. basic_cstring<CharT>::null_str()
  167. {
  168. return &null;
  169. }
  170. //____________________________________________________________________________//
  171. template<typename CharT>
  172. inline
  173. basic_cstring<CharT>::basic_cstring()
  174. : m_begin( null_str() )
  175. , m_end( m_begin )
  176. {
  177. }
  178. //____________________________________________________________________________//
  179. template<typename CharT>
  180. inline
  181. basic_cstring<CharT>::basic_cstring(basic_cstring const & s)
  182. : m_begin( s.m_begin )
  183. , m_end( s.m_end )
  184. {
  185. }
  186. //____________________________________________________________________________//
  187. template<typename CharT>
  188. inline
  189. basic_cstring<CharT>::basic_cstring( std_string const& s )
  190. : m_begin( s.c_str() )
  191. , m_end( m_begin + s.size() )
  192. {
  193. }
  194. //____________________________________________________________________________//
  195. template<typename CharT>
  196. inline
  197. basic_cstring<CharT>::basic_cstring( pointer s )
  198. : m_begin( s ? s : null_str() )
  199. , m_end ( m_begin + (s ? traits_type::length( s ) : 0 ) )
  200. {
  201. }
  202. //____________________________________________________________________________//
  203. template<typename CharT>
  204. inline
  205. basic_cstring<CharT>::basic_cstring( pointer first, pointer last )
  206. : m_begin( first )
  207. , m_end( last )
  208. {
  209. }
  210. //____________________________________________________________________________//
  211. template<typename CharT>
  212. inline typename basic_cstring<CharT>::value_ret_type
  213. basic_cstring<CharT>::operator[]( size_type index ) const
  214. {
  215. return m_begin[index];
  216. }
  217. //____________________________________________________________________________//
  218. template<typename CharT>
  219. inline typename basic_cstring<CharT>::value_ret_type
  220. basic_cstring<CharT>::at( size_type index ) const
  221. {
  222. if( m_begin + index >= m_end )
  223. return static_cast<value_type>(0);
  224. return m_begin[index];
  225. }
  226. //____________________________________________________________________________//
  227. template<typename CharT>
  228. inline typename basic_cstring<CharT>::size_type
  229. basic_cstring<CharT>::size() const
  230. {
  231. return static_cast<size_type>(m_end - m_begin);
  232. }
  233. //____________________________________________________________________________//
  234. template<typename CharT>
  235. inline bool
  236. basic_cstring<CharT>::is_empty() const
  237. {
  238. return m_end == m_begin;
  239. }
  240. //____________________________________________________________________________//
  241. template<typename CharT>
  242. inline bool
  243. basic_cstring<CharT>::empty() const
  244. {
  245. return is_empty();
  246. }
  247. //____________________________________________________________________________//
  248. template<typename CharT>
  249. inline void
  250. basic_cstring<CharT>::clear()
  251. {
  252. m_begin = m_end;
  253. }
  254. //____________________________________________________________________________//
  255. template<typename CharT>
  256. inline void
  257. basic_cstring<CharT>::resize( size_type new_len )
  258. {
  259. if( m_begin + new_len < m_end )
  260. m_end = m_begin + new_len;
  261. }
  262. //____________________________________________________________________________//
  263. template<typename CharT>
  264. inline basic_cstring<CharT>&
  265. basic_cstring<CharT>::trim_left( size_type trim_size )
  266. {
  267. m_begin += trim_size;
  268. if( m_end <= m_begin )
  269. clear();
  270. return *this;
  271. }
  272. //____________________________________________________________________________//
  273. template<typename CharT>
  274. inline basic_cstring<CharT>&
  275. basic_cstring<CharT>::trim_left( iterator it )
  276. {
  277. m_begin = it;
  278. if( m_end <= m_begin )
  279. clear();
  280. return *this;
  281. }
  282. //____________________________________________________________________________//
  283. template<typename CharT>
  284. inline basic_cstring<CharT>&
  285. basic_cstring<CharT>::trim_left( basic_cstring exclusions )
  286. {
  287. if( exclusions.is_empty() )
  288. exclusions = default_trim_ex();
  289. iterator it;
  290. for( it = begin(); it != end(); ++it ) {
  291. if( traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
  292. break;
  293. }
  294. return trim_left( it );
  295. }
  296. //____________________________________________________________________________//
  297. template<typename CharT>
  298. inline basic_cstring<CharT>&
  299. basic_cstring<CharT>::trim_right( size_type trim_size )
  300. {
  301. m_end -= trim_size;
  302. if( m_end <= m_begin )
  303. clear();
  304. return *this;
  305. }
  306. //____________________________________________________________________________//
  307. template<typename CharT>
  308. inline basic_cstring<CharT>&
  309. basic_cstring<CharT>::trim_right( iterator it )
  310. {
  311. m_end = it;
  312. if( m_end <= m_begin )
  313. clear();
  314. return *this;
  315. }
  316. //____________________________________________________________________________//
  317. template<typename CharT>
  318. inline basic_cstring<CharT>&
  319. basic_cstring<CharT>::trim_right( basic_cstring exclusions )
  320. {
  321. if( exclusions.is_empty() )
  322. exclusions = default_trim_ex();
  323. iterator it;
  324. for( it = end()-1; it != begin()-1; --it ) {
  325. if( self_type::traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
  326. break;
  327. }
  328. return trim_right( it+1 );
  329. }
  330. //____________________________________________________________________________//
  331. template<typename CharT>
  332. inline basic_cstring<CharT>&
  333. basic_cstring<CharT>::trim( basic_cstring exclusions )
  334. {
  335. trim_left( exclusions );
  336. trim_right( exclusions );
  337. return *this;
  338. }
  339. //____________________________________________________________________________//
  340. template<typename CharT>
  341. inline basic_cstring<CharT>&
  342. basic_cstring<CharT>::operator=( basic_cstring<CharT> const& s )
  343. {
  344. m_begin = s.m_begin;
  345. m_end = s.m_end;
  346. return *this;
  347. }
  348. //____________________________________________________________________________//
  349. template<typename CharT>
  350. inline basic_cstring<CharT>&
  351. basic_cstring<CharT>::operator=( std_string const& s )
  352. {
  353. return *this = self_type( s );
  354. }
  355. //____________________________________________________________________________//
  356. template<typename CharT>
  357. inline basic_cstring<CharT>&
  358. basic_cstring<CharT>::operator=( pointer s )
  359. {
  360. return *this = self_type( s );
  361. }
  362. //____________________________________________________________________________//
  363. template<typename CharT>
  364. inline basic_cstring<CharT>&
  365. basic_cstring<CharT>::assign( std_string const& s )
  366. {
  367. return *this = self_type( s );
  368. }
  369. //____________________________________________________________________________//
  370. template<typename CharT>
  371. inline basic_cstring<CharT>&
  372. basic_cstring<CharT>::assign( pointer s )
  373. {
  374. return *this = self_type( s );
  375. }
  376. //____________________________________________________________________________//
  377. template<typename CharT>
  378. inline basic_cstring<CharT>&
  379. basic_cstring<CharT>::assign( pointer f, pointer l )
  380. {
  381. return *this = self_type( f, l );
  382. }
  383. //____________________________________________________________________________//
  384. template<typename CharT>
  385. inline void
  386. basic_cstring<CharT>::swap( basic_cstring<CharT>& s )
  387. {
  388. // do not want to include alogrithm
  389. pointer tmp1 = m_begin;
  390. pointer tmp2 = m_end;
  391. m_begin = s.m_begin;
  392. m_end = s.m_end;
  393. s.m_begin = tmp1;
  394. s.m_end = tmp2;
  395. }
  396. //____________________________________________________________________________//
  397. template<typename CharT>
  398. inline typename basic_cstring<CharT>::iterator
  399. basic_cstring<CharT>::begin()
  400. {
  401. return m_begin;
  402. }
  403. //____________________________________________________________________________//
  404. template<typename CharT>
  405. inline typename basic_cstring<CharT>::const_iterator
  406. basic_cstring<CharT>::begin() const
  407. {
  408. return m_begin;
  409. }
  410. //____________________________________________________________________________//
  411. template<typename CharT>
  412. inline typename basic_cstring<CharT>::iterator
  413. basic_cstring<CharT>::end()
  414. {
  415. return m_end;
  416. }
  417. //____________________________________________________________________________//
  418. template<typename CharT>
  419. inline typename basic_cstring<CharT>::const_iterator
  420. basic_cstring<CharT>::end() const
  421. {
  422. return m_end;
  423. }
  424. //____________________________________________________________________________//
  425. template<typename CharT>
  426. inline typename basic_cstring<CharT>::size_type
  427. basic_cstring<CharT>::find( basic_cstring<CharT> str ) const
  428. {
  429. if( str.is_empty() || str.size() > size() )
  430. return static_cast<size_type>(npos);
  431. const_iterator it = begin();
  432. const_iterator last = end() - str.size() + 1;
  433. while( it != last ) {
  434. if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
  435. break;
  436. ++it;
  437. }
  438. return it == last ? npos : static_cast<size_type>(it - begin());
  439. }
  440. //____________________________________________________________________________//
  441. template<typename CharT>
  442. inline typename basic_cstring<CharT>::size_type
  443. basic_cstring<CharT>::rfind( basic_cstring<CharT> str ) const
  444. {
  445. if( str.is_empty() || str.size() > size() )
  446. return static_cast<size_type>(npos);
  447. const_iterator it = end() - str.size();
  448. const_iterator last = begin()-1;
  449. while( it != last ) {
  450. if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
  451. break;
  452. --it;
  453. }
  454. return it == last ? static_cast<size_type>(npos) : static_cast<size_type>(it - begin());
  455. }
  456. //____________________________________________________________________________//
  457. template<typename CharT>
  458. inline basic_cstring<CharT>
  459. basic_cstring<CharT>::substr( size_type beg_index, size_type end_index ) const
  460. {
  461. return beg_index > size()
  462. ? self_type()
  463. : end_index > size()
  464. ? self_type( m_begin + beg_index, m_end )
  465. : self_type( m_begin + beg_index, m_begin + end_index );
  466. }
  467. //____________________________________________________________________________//
  468. template<typename CharT>
  469. inline basic_cstring<CharT>
  470. basic_cstring<CharT>::default_trim_ex()
  471. {
  472. static CharT ws[3] = { CharT(' '), CharT('\t'), CharT('\n') }; // !! wide case
  473. return self_type( ws, 3 );
  474. }
  475. //____________________________________________________________________________//
  476. // ************************************************************************** //
  477. // ************** comparison operators ************** //
  478. // ************************************************************************** //
  479. template<typename CharT1,typename CharT2>
  480. inline bool
  481. operator==( basic_cstring<CharT1> const& s1, basic_cstring<CharT2> const& s2 )
  482. {
  483. typedef typename basic_cstring<CharT1>::traits_type traits_type;
  484. return s1.size() == s2.size() &&
  485. traits_type::compare( s1.begin(), s2.begin(), s1.size() ) == 0;
  486. }
  487. //____________________________________________________________________________//
  488. template<typename CharT1,typename CharT2>
  489. inline bool
  490. operator==( basic_cstring<CharT1> const& s1, CharT2* s2 )
  491. {
  492. #if !defined(__DMC__)
  493. return s1 == basic_cstring<CharT2>( s2 );
  494. #else
  495. return s1 == basic_cstring<CharT2 const>( s2 );
  496. #endif
  497. }
  498. //____________________________________________________________________________//
  499. template<typename CharT>
  500. inline bool
  501. operator==( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
  502. {
  503. return s1 == basic_cstring<CharT>( s2 );
  504. }
  505. //____________________________________________________________________________//
  506. template<typename CharT1,typename CharT2>
  507. inline bool
  508. operator==( CharT1* s2, basic_cstring<CharT2> const& s1 )
  509. {
  510. return s1 == s2;
  511. }
  512. //____________________________________________________________________________//
  513. template<typename CharT>
  514. inline bool
  515. operator==( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
  516. {
  517. return s1 == s2;
  518. }
  519. //____________________________________________________________________________//
  520. template<typename CharT>
  521. inline bool
  522. operator!=( basic_cstring<CharT> const& s1, CharT* s2 )
  523. {
  524. return !(s1 == s2);
  525. }
  526. //____________________________________________________________________________//
  527. template<typename CharT>
  528. inline bool
  529. operator!=( CharT* s2, basic_cstring<CharT> const& s1 )
  530. {
  531. return !(s1 == s2);
  532. }
  533. //____________________________________________________________________________//
  534. template<typename CharT>
  535. inline bool
  536. operator!=( basic_cstring<CharT> const& s1, basic_cstring<CharT> const& s2 )
  537. {
  538. return !(s1 == s2);
  539. }
  540. //____________________________________________________________________________//
  541. template<typename CharT>
  542. inline bool
  543. operator!=( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
  544. {
  545. return !(s1 == s2);
  546. }
  547. //____________________________________________________________________________//
  548. template<typename CharT>
  549. inline bool
  550. operator!=( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
  551. {
  552. return !(s1 == s2);
  553. }
  554. //____________________________________________________________________________//
  555. // ************************************************************************** //
  556. // ************** first_char ************** //
  557. // ************************************************************************** //
  558. template<typename CharT>
  559. inline typename basic_cstring<CharT>::value_ret_type
  560. first_char( basic_cstring<CharT> source )
  561. {
  562. typedef typename basic_cstring<CharT>::value_ret_type res_type;
  563. return source.is_empty() ? static_cast<res_type>(0) : *source.begin();
  564. }
  565. //____________________________________________________________________________//
  566. // ************************************************************************** //
  567. // ************** last_char ************** //
  568. // ************************************************************************** //
  569. template<typename CharT>
  570. inline typename basic_cstring<CharT>::value_ret_type
  571. last_char( basic_cstring<CharT> source )
  572. {
  573. typedef typename basic_cstring<CharT>::value_ret_type res_type;
  574. return source.is_empty() ? static_cast<res_type>(0) : *(source.end()-1);
  575. }
  576. //____________________________________________________________________________//
  577. // ************************************************************************** //
  578. // ************** assign_op ************** //
  579. // ************************************************************************** //
  580. template<typename CharT1, typename CharT2>
  581. inline void
  582. assign_op( std::basic_string<CharT1>& target, basic_cstring<CharT2> src, int )
  583. {
  584. target.assign( src.begin(), src.size() );
  585. }
  586. //____________________________________________________________________________//
  587. template<typename CharT1, typename CharT2>
  588. inline std::basic_string<CharT1>&
  589. operator+=( std::basic_string<CharT1>& target, basic_cstring<CharT2> const& str )
  590. {
  591. target.append( str.begin(), str.end() );
  592. return target;
  593. }
  594. //____________________________________________________________________________//
  595. template<typename CharT1, typename CharT2>
  596. inline std::basic_string<CharT1>
  597. operator+( std::basic_string<CharT1> const& lhs, basic_cstring<CharT2> const& rhs )
  598. {
  599. std::basic_string<CharT1> res( lhs );
  600. res.append( rhs.begin(), rhs.end() );
  601. return res;
  602. }
  603. //____________________________________________________________________________//
  604. } // namespace unit_test
  605. } // namespace boost
  606. //____________________________________________________________________________//
  607. #include <boost/test/detail/enable_warnings.hpp>
  608. #endif // BOOST_TEST_UTILS_BASIC_CSTRING_HPP