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

source code of boost/libs/test/include/boost/test/utils/basic_cstring/basic_cstring.hpp