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 | |
37 | namespace boost { |
38 | |
39 | namespace unit_test { |
40 | |
41 | // ************************************************************************** // |
42 | // ************** basic_cstring ************** // |
43 | // ************************************************************************** // |
44 | |
45 | template<typename CharT> |
46 | class BOOST_SYMBOL_VISIBLE basic_cstring { |
47 | typedef basic_cstring<CharT> self_type; |
48 | public: |
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 | |
164 | private: |
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 |
183 | template <class CharT, class string_view_t = std::basic_string_view<CharT>> |
184 | class BOOST_SYMBOL_VISIBLE stringview_cstring_helper : public basic_cstring<CharT> { |
185 | public: |
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 | |
199 | template<typename CharT> |
200 | CharT basic_cstring<CharT>::null = 0; |
201 | |
202 | //____________________________________________________________________________// |
203 | |
204 | template<typename CharT> |
205 | inline typename basic_cstring<CharT>::pointer |
206 | basic_cstring<CharT>::null_str() |
207 | { |
208 | return &null; |
209 | } |
210 | |
211 | //____________________________________________________________________________// |
212 | |
213 | template<typename CharT> |
214 | inline |
215 | basic_cstring<CharT>::basic_cstring() |
216 | : m_begin( null_str() ) |
217 | , m_end( m_begin ) |
218 | { |
219 | } |
220 | |
221 | //____________________________________________________________________________// |
222 | |
223 | template<typename CharT> |
224 | inline |
225 | basic_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 | |
233 | template<typename CharT> |
234 | inline |
235 | basic_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 | |
243 | template<typename CharT> |
244 | inline |
245 | basic_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 | |
253 | template<typename CharT> |
254 | inline |
255 | basic_cstring<CharT>::basic_cstring( pointer first, pointer last ) |
256 | : m_begin( first ) |
257 | , m_end( last ) |
258 | { |
259 | } |
260 | |
261 | //____________________________________________________________________________// |
262 | |
263 | template<typename CharT> |
264 | inline typename basic_cstring<CharT>::value_ret_type |
265 | basic_cstring<CharT>::operator[]( size_type index ) const |
266 | { |
267 | return m_begin[index]; |
268 | } |
269 | |
270 | //____________________________________________________________________________// |
271 | |
272 | template<typename CharT> |
273 | inline typename basic_cstring<CharT>::value_ret_type |
274 | basic_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 | |
284 | template<typename CharT> |
285 | inline typename basic_cstring<CharT>::size_type |
286 | basic_cstring<CharT>::size() const |
287 | { |
288 | return static_cast<size_type>(m_end - m_begin); |
289 | } |
290 | |
291 | //____________________________________________________________________________// |
292 | |
293 | template<typename CharT> |
294 | inline bool |
295 | basic_cstring<CharT>::is_empty() const |
296 | { |
297 | return m_end == m_begin; |
298 | } |
299 | |
300 | //____________________________________________________________________________// |
301 | |
302 | template<typename CharT> |
303 | inline bool |
304 | basic_cstring<CharT>::empty() const |
305 | { |
306 | return is_empty(); |
307 | } |
308 | |
309 | //____________________________________________________________________________// |
310 | |
311 | template<typename CharT> |
312 | inline void |
313 | basic_cstring<CharT>::clear() |
314 | { |
315 | m_begin = m_end; |
316 | } |
317 | |
318 | //____________________________________________________________________________// |
319 | |
320 | template<typename CharT> |
321 | inline void |
322 | basic_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 | |
330 | template<typename CharT> |
331 | inline basic_cstring<CharT>& |
332 | basic_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 | |
343 | template<typename CharT> |
344 | inline basic_cstring<CharT>& |
345 | basic_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 | |
356 | template<typename CharT> |
357 | inline basic_cstring<CharT>& |
358 | basic_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 | |
374 | template<typename CharT> |
375 | inline basic_cstring<CharT>& |
376 | basic_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 | |
387 | template<typename CharT> |
388 | inline basic_cstring<CharT>& |
389 | basic_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 | |
400 | template<typename CharT> |
401 | inline basic_cstring<CharT>& |
402 | basic_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 | |
424 | template<typename CharT> |
425 | inline basic_cstring<CharT>& |
426 | basic_cstring<CharT>::trim( basic_cstring exclusions ) |
427 | { |
428 | trim_left( exclusions ); |
429 | trim_right( exclusions ); |
430 | |
431 | return *this; |
432 | } |
433 | |
434 | //____________________________________________________________________________// |
435 | |
436 | template<typename CharT> |
437 | inline basic_cstring<CharT>& |
438 | basic_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 | |
448 | template<typename CharT> |
449 | inline basic_cstring<CharT>& |
450 | basic_cstring<CharT>::operator=( std_string const& s ) |
451 | { |
452 | return *this = self_type( s ); |
453 | } |
454 | |
455 | //____________________________________________________________________________// |
456 | |
457 | template<typename CharT> |
458 | inline basic_cstring<CharT>& |
459 | basic_cstring<CharT>::operator=( pointer s ) |
460 | { |
461 | return *this = self_type( s ); |
462 | } |
463 | |
464 | //____________________________________________________________________________// |
465 | |
466 | template<typename CharT> |
467 | inline basic_cstring<CharT>& |
468 | basic_cstring<CharT>::assign( std_string const& s ) |
469 | { |
470 | return *this = self_type( s ); |
471 | } |
472 | |
473 | //____________________________________________________________________________// |
474 | |
475 | template<typename CharT> |
476 | inline basic_cstring<CharT>& |
477 | basic_cstring<CharT>::assign( pointer s ) |
478 | { |
479 | return *this = self_type( s ); |
480 | } |
481 | |
482 | //____________________________________________________________________________// |
483 | |
484 | template<typename CharT> |
485 | inline basic_cstring<CharT>& |
486 | basic_cstring<CharT>::assign( pointer f, pointer l ) |
487 | { |
488 | return *this = self_type( f, l ); |
489 | } |
490 | |
491 | //____________________________________________________________________________// |
492 | |
493 | template<typename CharT> |
494 | inline void |
495 | basic_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 | |
510 | template<typename CharT> |
511 | inline typename basic_cstring<CharT>::iterator |
512 | basic_cstring<CharT>::begin() |
513 | { |
514 | return m_begin; |
515 | } |
516 | |
517 | //____________________________________________________________________________// |
518 | |
519 | template<typename CharT> |
520 | inline typename basic_cstring<CharT>::const_iterator |
521 | basic_cstring<CharT>::begin() const |
522 | { |
523 | return m_begin; |
524 | } |
525 | |
526 | //____________________________________________________________________________// |
527 | |
528 | template<typename CharT> |
529 | inline typename basic_cstring<CharT>::iterator |
530 | basic_cstring<CharT>::end() |
531 | { |
532 | return m_end; |
533 | } |
534 | |
535 | //____________________________________________________________________________// |
536 | |
537 | template<typename CharT> |
538 | inline typename basic_cstring<CharT>::const_iterator |
539 | basic_cstring<CharT>::end() const |
540 | { |
541 | return m_end; |
542 | } |
543 | |
544 | //____________________________________________________________________________// |
545 | |
546 | template<typename CharT> |
547 | inline typename basic_cstring<CharT>::size_type |
548 | basic_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 | |
565 | template<typename CharT> |
566 | inline typename basic_cstring<CharT>::size_type |
567 | basic_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 | |
586 | template<typename CharT> |
587 | inline basic_cstring<CharT> |
588 | basic_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 | |
599 | template<typename CharT> |
600 | inline basic_cstring<CharT> |
601 | basic_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 | |
614 | template<typename CharT1,typename CharT2> |
615 | inline bool |
616 | operator==( 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 | |
625 | template<typename CharT1,typename CharT2> |
626 | inline bool |
627 | operator==( 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 | |
638 | template<typename CharT> |
639 | inline bool |
640 | operator==( 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 | |
647 | template<typename CharT1,typename CharT2> |
648 | inline bool |
649 | operator==( CharT1* s2, basic_cstring<CharT2> const& s1 ) |
650 | { |
651 | return s1 == s2; |
652 | } |
653 | |
654 | //____________________________________________________________________________// |
655 | |
656 | template<typename CharT> |
657 | inline bool |
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 | template<typename CharT> |
666 | inline bool |
667 | operator!=( basic_cstring<CharT> const& s1, CharT* s2 ) |
668 | { |
669 | return !(s1 == s2); |
670 | } |
671 | |
672 | //____________________________________________________________________________// |
673 | |
674 | template<typename CharT> |
675 | inline bool |
676 | operator!=( CharT* s2, basic_cstring<CharT> const& s1 ) |
677 | { |
678 | return !(s1 == s2); |
679 | } |
680 | |
681 | //____________________________________________________________________________// |
682 | |
683 | template<typename CharT> |
684 | inline bool |
685 | operator!=( basic_cstring<CharT> const& s1, basic_cstring<CharT> const& s2 ) |
686 | { |
687 | return !(s1 == s2); |
688 | } |
689 | |
690 | //____________________________________________________________________________// |
691 | |
692 | template<typename CharT> |
693 | inline bool |
694 | operator!=( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 ) |
695 | { |
696 | return !(s1 == s2); |
697 | } |
698 | |
699 | //____________________________________________________________________________// |
700 | |
701 | template<typename CharT> |
702 | inline bool |
703 | operator!=( 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 | |
714 | template<typename CharT> |
715 | inline typename basic_cstring<CharT>::value_ret_type |
716 | first_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 | |
729 | template<typename CharT> |
730 | inline typename basic_cstring<CharT>::value_ret_type |
731 | last_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 | |
744 | template<typename CharT1, typename CharT2> |
745 | inline void |
746 | assign_op( std::basic_string<CharT1>& target, basic_cstring<CharT2> src, int ) |
747 | { |
748 | target.assign( src.begin(), src.size() ); |
749 | } |
750 | |
751 | //____________________________________________________________________________// |
752 | |
753 | template<typename CharT1, typename CharT2> |
754 | inline std::basic_string<CharT1>& |
755 | operator+=( 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 | |
763 | template<typename CharT1, typename CharT2> |
764 | inline std::basic_string<CharT1> |
765 | operator+( 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 | |