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