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