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( exclusions.is_empty() ) |
405 | exclusions = default_trim_ex(); |
406 | |
407 | iterator it; |
408 | |
409 | for( it = end()-1; it != begin()-1; --it ) { |
410 | if( self_type::traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) ) |
411 | break; |
412 | } |
413 | |
414 | return trim_right( it+1 ); |
415 | } |
416 | |
417 | //____________________________________________________________________________// |
418 | |
419 | template<typename CharT> |
420 | inline basic_cstring<CharT>& |
421 | basic_cstring<CharT>::trim( basic_cstring exclusions ) |
422 | { |
423 | trim_left( exclusions ); |
424 | trim_right( exclusions ); |
425 | |
426 | return *this; |
427 | } |
428 | |
429 | //____________________________________________________________________________// |
430 | |
431 | template<typename CharT> |
432 | inline basic_cstring<CharT>& |
433 | basic_cstring<CharT>::operator=( basic_cstring<CharT> const& s ) |
434 | { |
435 | m_begin = s.m_begin; |
436 | m_end = s.m_end; |
437 | |
438 | return *this; |
439 | } |
440 | |
441 | //____________________________________________________________________________// |
442 | |
443 | template<typename CharT> |
444 | inline basic_cstring<CharT>& |
445 | basic_cstring<CharT>::operator=( std_string const& s ) |
446 | { |
447 | return *this = self_type( s ); |
448 | } |
449 | |
450 | //____________________________________________________________________________// |
451 | |
452 | template<typename CharT> |
453 | inline basic_cstring<CharT>& |
454 | basic_cstring<CharT>::operator=( pointer s ) |
455 | { |
456 | return *this = self_type( s ); |
457 | } |
458 | |
459 | //____________________________________________________________________________// |
460 | |
461 | template<typename CharT> |
462 | inline basic_cstring<CharT>& |
463 | basic_cstring<CharT>::assign( std_string const& s ) |
464 | { |
465 | return *this = self_type( s ); |
466 | } |
467 | |
468 | //____________________________________________________________________________// |
469 | |
470 | template<typename CharT> |
471 | inline basic_cstring<CharT>& |
472 | basic_cstring<CharT>::assign( pointer s ) |
473 | { |
474 | return *this = self_type( s ); |
475 | } |
476 | |
477 | //____________________________________________________________________________// |
478 | |
479 | template<typename CharT> |
480 | inline basic_cstring<CharT>& |
481 | basic_cstring<CharT>::assign( pointer f, pointer l ) |
482 | { |
483 | return *this = self_type( f, l ); |
484 | } |
485 | |
486 | //____________________________________________________________________________// |
487 | |
488 | template<typename CharT> |
489 | inline void |
490 | basic_cstring<CharT>::swap( basic_cstring<CharT>& s ) |
491 | { |
492 | // do not want to include alogrithm |
493 | pointer tmp1 = m_begin; |
494 | pointer tmp2 = m_end; |
495 | |
496 | m_begin = s.m_begin; |
497 | m_end = s.m_end; |
498 | |
499 | s.m_begin = tmp1; |
500 | s.m_end = tmp2; |
501 | } |
502 | |
503 | //____________________________________________________________________________// |
504 | |
505 | template<typename CharT> |
506 | inline typename basic_cstring<CharT>::iterator |
507 | basic_cstring<CharT>::begin() |
508 | { |
509 | return m_begin; |
510 | } |
511 | |
512 | //____________________________________________________________________________// |
513 | |
514 | template<typename CharT> |
515 | inline typename basic_cstring<CharT>::const_iterator |
516 | basic_cstring<CharT>::begin() const |
517 | { |
518 | return m_begin; |
519 | } |
520 | |
521 | //____________________________________________________________________________// |
522 | |
523 | template<typename CharT> |
524 | inline typename basic_cstring<CharT>::iterator |
525 | basic_cstring<CharT>::end() |
526 | { |
527 | return m_end; |
528 | } |
529 | |
530 | //____________________________________________________________________________// |
531 | |
532 | template<typename CharT> |
533 | inline typename basic_cstring<CharT>::const_iterator |
534 | basic_cstring<CharT>::end() const |
535 | { |
536 | return m_end; |
537 | } |
538 | |
539 | //____________________________________________________________________________// |
540 | |
541 | template<typename CharT> |
542 | inline typename basic_cstring<CharT>::size_type |
543 | basic_cstring<CharT>::find( basic_cstring<CharT> str ) const |
544 | { |
545 | if( str.is_empty() || str.size() > size() ) |
546 | return static_cast<size_type>(npos); |
547 | |
548 | const_iterator it = begin(); |
549 | const_iterator last = end() - str.size() + 1; |
550 | |
551 | while( it != last ) { |
552 | if( traits_type::compare( it, str.begin(), str.size() ) == 0 ) |
553 | break; |
554 | |
555 | ++it; |
556 | } |
557 | |
558 | return it == last ? npos : static_cast<size_type>(it - begin()); |
559 | } |
560 | |
561 | //____________________________________________________________________________// |
562 | |
563 | template<typename CharT> |
564 | inline typename basic_cstring<CharT>::size_type |
565 | basic_cstring<CharT>::rfind( basic_cstring<CharT> str ) const |
566 | { |
567 | if( str.is_empty() || str.size() > size() ) |
568 | return static_cast<size_type>(npos); |
569 | |
570 | const_iterator it = end() - str.size(); |
571 | const_iterator last = begin()-1; |
572 | |
573 | while( it != last ) { |
574 | if( traits_type::compare( it, str.begin(), str.size() ) == 0 ) |
575 | break; |
576 | |
577 | --it; |
578 | } |
579 | |
580 | return it == last ? static_cast<size_type>(npos) : static_cast<size_type>(it - begin()); |
581 | } |
582 | |
583 | //____________________________________________________________________________// |
584 | |
585 | template<typename CharT> |
586 | inline basic_cstring<CharT> |
587 | basic_cstring<CharT>::substr( size_type beg_index, size_type end_index ) const |
588 | { |
589 | return beg_index > size() |
590 | ? self_type() |
591 | : end_index > size() |
592 | ? self_type( m_begin + beg_index, m_end ) |
593 | : self_type( m_begin + beg_index, m_begin + end_index ); |
594 | } |
595 | |
596 | //____________________________________________________________________________// |
597 | |
598 | template<typename CharT> |
599 | inline basic_cstring<CharT> |
600 | basic_cstring<CharT>::default_trim_ex() |
601 | { |
602 | static CharT ws[3] = { CharT(' '), CharT('\t'), CharT('\n') }; // !! wide case |
603 | |
604 | return self_type( ws, 3 ); |
605 | } |
606 | |
607 | //____________________________________________________________________________// |
608 | |
609 | // ************************************************************************** // |
610 | // ************** comparison operators ************** // |
611 | // ************************************************************************** // |
612 | |
613 | template<typename CharT1,typename CharT2> |
614 | inline bool |
615 | operator==( basic_cstring<CharT1> const& s1, basic_cstring<CharT2> const& s2 ) |
616 | { |
617 | typedef typename basic_cstring<CharT1>::traits_type traits_type; |
618 | return s1.size() == s2.size() && |
619 | traits_type::compare( s1.begin(), s2.begin(), s1.size() ) == 0; |
620 | } |
621 | |
622 | //____________________________________________________________________________// |
623 | |
624 | template<typename CharT1,typename CharT2> |
625 | inline bool |
626 | operator==( basic_cstring<CharT1> const& s1, CharT2* s2 ) |
627 | { |
628 | #if !defined(__DMC__) |
629 | return s1 == basic_cstring<CharT2>( s2 ); |
630 | #else |
631 | return s1 == basic_cstring<CharT2 const>( s2 ); |
632 | #endif |
633 | } |
634 | |
635 | //____________________________________________________________________________// |
636 | |
637 | template<typename CharT> |
638 | inline bool |
639 | operator==( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 ) |
640 | { |
641 | return s1 == basic_cstring<CharT>( s2 ); |
642 | } |
643 | |
644 | //____________________________________________________________________________// |
645 | |
646 | template<typename CharT1,typename CharT2> |
647 | inline bool |
648 | operator==( CharT1* s2, basic_cstring<CharT2> const& s1 ) |
649 | { |
650 | return s1 == s2; |
651 | } |
652 | |
653 | //____________________________________________________________________________// |
654 | |
655 | template<typename CharT> |
656 | inline bool |
657 | operator==( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 ) |
658 | { |
659 | return s1 == s2; |
660 | } |
661 | |
662 | //____________________________________________________________________________// |
663 | |
664 | template<typename CharT> |
665 | inline bool |
666 | operator!=( basic_cstring<CharT> const& s1, CharT* s2 ) |
667 | { |
668 | return !(s1 == s2); |
669 | } |
670 | |
671 | //____________________________________________________________________________// |
672 | |
673 | template<typename CharT> |
674 | inline bool |
675 | operator!=( CharT* s2, basic_cstring<CharT> const& s1 ) |
676 | { |
677 | return !(s1 == s2); |
678 | } |
679 | |
680 | //____________________________________________________________________________// |
681 | |
682 | template<typename CharT> |
683 | inline bool |
684 | operator!=( basic_cstring<CharT> const& s1, basic_cstring<CharT> const& s2 ) |
685 | { |
686 | return !(s1 == s2); |
687 | } |
688 | |
689 | //____________________________________________________________________________// |
690 | |
691 | template<typename CharT> |
692 | inline bool |
693 | operator!=( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 ) |
694 | { |
695 | return !(s1 == s2); |
696 | } |
697 | |
698 | //____________________________________________________________________________// |
699 | |
700 | template<typename CharT> |
701 | inline bool |
702 | operator!=( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 ) |
703 | { |
704 | return !(s1 == s2); |
705 | } |
706 | |
707 | //____________________________________________________________________________// |
708 | |
709 | // ************************************************************************** // |
710 | // ************** first_char ************** // |
711 | // ************************************************************************** // |
712 | |
713 | template<typename CharT> |
714 | inline typename basic_cstring<CharT>::value_ret_type |
715 | first_char( basic_cstring<CharT> source ) |
716 | { |
717 | typedef typename basic_cstring<CharT>::value_ret_type res_type; |
718 | |
719 | return source.is_empty() ? static_cast<res_type>(0) : *source.begin(); |
720 | } |
721 | |
722 | //____________________________________________________________________________// |
723 | |
724 | // ************************************************************************** // |
725 | // ************** last_char ************** // |
726 | // ************************************************************************** // |
727 | |
728 | template<typename CharT> |
729 | inline typename basic_cstring<CharT>::value_ret_type |
730 | last_char( basic_cstring<CharT> source ) |
731 | { |
732 | typedef typename basic_cstring<CharT>::value_ret_type res_type; |
733 | |
734 | return source.is_empty() ? static_cast<res_type>(0) : *(source.end()-1); |
735 | } |
736 | |
737 | //____________________________________________________________________________// |
738 | |
739 | // ************************************************************************** // |
740 | // ************** assign_op ************** // |
741 | // ************************************************************************** // |
742 | |
743 | template<typename CharT1, typename CharT2> |
744 | inline void |
745 | assign_op( std::basic_string<CharT1>& target, basic_cstring<CharT2> src, int ) |
746 | { |
747 | target.assign( src.begin(), src.size() ); |
748 | } |
749 | |
750 | //____________________________________________________________________________// |
751 | |
752 | template<typename CharT1, typename CharT2> |
753 | inline std::basic_string<CharT1>& |
754 | operator+=( std::basic_string<CharT1>& target, basic_cstring<CharT2> const& str ) |
755 | { |
756 | target.append( str.begin(), str.end() ); |
757 | return target; |
758 | } |
759 | |
760 | //____________________________________________________________________________// |
761 | |
762 | template<typename CharT1, typename CharT2> |
763 | inline std::basic_string<CharT1> |
764 | operator+( std::basic_string<CharT1> const& lhs, basic_cstring<CharT2> const& rhs ) |
765 | { |
766 | std::basic_string<CharT1> res( lhs ); |
767 | |
768 | res.append( rhs.begin(), rhs.end() ); |
769 | return res; |
770 | } |
771 | |
772 | //____________________________________________________________________________// |
773 | |
774 | } // namespace unit_test |
775 | |
776 | } // namespace boost |
777 | |
778 | //____________________________________________________________________________// |
779 | |
780 | #include <boost/test/detail/enable_warnings.hpp> |
781 | |
782 | #endif // BOOST_TEST_UTILS_BASIC_CSTRING_HPP |
783 | |