blob: 41a64cd3c319cd7654c130ad2ea27b25eff176ca [file] [log] [blame]
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001// (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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070016#ifndef NDNBOOST_TEST_BASIC_CSTRING_HPP_071894GER
17#define NDNBOOST_TEST_BASIC_CSTRING_HPP_071894GER
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070018
19// Boost.Test
20#include <ndnboost/test/utils/basic_cstring/basic_cstring_fwd.hpp>
21#include <ndnboost/test/utils/basic_cstring/bcs_char_traits.hpp>
22
23// STL
24#include <string>
25
26#include <ndnboost/test/detail/suppress_warnings.hpp>
27
28//____________________________________________________________________________//
29
30namespace ndnboost {
31
32namespace unit_test {
33
34// ************************************************************************** //
35// ************** basic_cstring ************** //
36// ************************************************************************** //
37
38template<typename CharT>
39class basic_cstring {
40 typedef basic_cstring<CharT> self_type;
41public:
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070059#if !NDNBOOST_WORKAROUND(__IBMCPP__, NDNBOOST_TESTED_AT(600))
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070060 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 ) ;
103 self_type& trim_left() { trim_left( self_type() ) ; }
104 self_type& trim_right() { trim_right( self_type() ) ; }
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>
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
138private:
139 static self_type default_trim_ex();
140
141 // Data members
142 iterator m_begin;
143 iterator m_end;
144};
145
146//____________________________________________________________________________//
147
148template<typename CharT>
149inline typename basic_cstring<CharT>::pointer
150basic_cstring<CharT>::null_str()
151{
152 static CharT null = 0;
153 return &null;
154}
155
156//____________________________________________________________________________//
157
158template<typename CharT>
159inline
160basic_cstring<CharT>::basic_cstring()
161: m_begin( null_str() )
162, m_end( m_begin )
163{
164}
165
166//____________________________________________________________________________//
167
168template<typename CharT>
169inline
170basic_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
178template<typename CharT>
179inline
180basic_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
188template<typename CharT>
189inline
190basic_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
197template<typename CharT>
198inline
199basic_cstring<CharT>::basic_cstring( pointer first, pointer last )
200: m_begin( first )
201, m_end( last )
202{
203}
204
205//____________________________________________________________________________//
206
207template<typename CharT>
208inline typename basic_cstring<CharT>::value_type
209basic_cstring<CharT>::operator[]( size_type index ) const
210{
211 return m_begin[index];
212}
213
214//____________________________________________________________________________//
215
216template<typename CharT>
217inline typename basic_cstring<CharT>::value_type
218basic_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
228template<typename CharT>
229inline typename basic_cstring<CharT>::size_type
230basic_cstring<CharT>::size() const
231{
232 return m_end - m_begin;
233}
234
235//____________________________________________________________________________//
236
237template<typename CharT>
238inline bool
239basic_cstring<CharT>::is_empty() const
240{
241 return m_end == m_begin;
242}
243
244//____________________________________________________________________________//
245
246template<typename CharT>
247inline bool
248basic_cstring<CharT>::empty() const
249{
250 return is_empty();
251}
252
253//____________________________________________________________________________//
254
255template<typename CharT>
256inline void
257basic_cstring<CharT>::clear()
258{
259 m_begin = m_end;
260}
261
262//____________________________________________________________________________//
263
264template<typename CharT>
265inline void
266basic_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
274template<typename CharT>
275inline basic_cstring<CharT>&
276basic_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
287template<typename CharT>
288inline basic_cstring<CharT>&
289basic_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
300template<typename CharT>
301inline basic_cstring<CharT>&
302basic_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
318template<typename CharT>
319inline basic_cstring<CharT>&
320basic_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
331template<typename CharT>
332inline basic_cstring<CharT>&
333basic_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
344template<typename CharT>
345inline basic_cstring<CharT>&
346basic_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
363template<typename CharT>
364inline basic_cstring<CharT>&
365basic_cstring<CharT>::trim( basic_cstring exclusions )
366{
367 trim_left( exclusions );
368 trim_right( exclusions );
369
370 return *this;
371}
372
373//____________________________________________________________________________//
374
375template<typename CharT>
376inline basic_cstring<CharT>&
377basic_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
387template<typename CharT>
388inline basic_cstring<CharT>&
389basic_cstring<CharT>::operator=( std_string const& s )
390{
391 return *this = self_type( s );
392}
393
394//____________________________________________________________________________//
395
396template<typename CharT>
397inline basic_cstring<CharT>&
398basic_cstring<CharT>::operator=( pointer s )
399{
400 return *this = self_type( s );
401}
402
403//____________________________________________________________________________//
404
405template<typename CharT>
406inline basic_cstring<CharT>&
407basic_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
414template<typename CharT>
415inline basic_cstring<CharT>&
416basic_cstring<CharT>::assign( std_string const& s )
417{
418 return *this = self_type( s );
419}
420
421//____________________________________________________________________________//
422
423template<typename CharT>
424inline basic_cstring<CharT>&
425basic_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
432template<typename CharT>
433inline basic_cstring<CharT>&
434basic_cstring<CharT>::assign( pointer s )
435{
436 return *this = self_type( s );
437}
438
439//____________________________________________________________________________//
440
441template<typename CharT>
442inline basic_cstring<CharT>&
443basic_cstring<CharT>::assign( pointer s, size_type len )
444{
445 return *this = self_type( s, len );
446}
447
448//____________________________________________________________________________//
449
450template<typename CharT>
451inline basic_cstring<CharT>&
452basic_cstring<CharT>::assign( pointer f, pointer l )
453{
454 return *this = self_type( f, l );
455}
456
457//____________________________________________________________________________//
458
459template<typename CharT>
460inline void
461basic_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
476template<typename CharT>
477inline typename basic_cstring<CharT>::iterator
478basic_cstring<CharT>::begin()
479{
480 return m_begin;
481}
482
483//____________________________________________________________________________//
484
485template<typename CharT>
486inline typename basic_cstring<CharT>::const_iterator
487basic_cstring<CharT>::begin() const
488{
489 return m_begin;
490}
491
492//____________________________________________________________________________//
493
494template<typename CharT>
495inline typename basic_cstring<CharT>::iterator
496basic_cstring<CharT>::end()
497{
498 return m_end;
499}
500
501//____________________________________________________________________________//
502
503template<typename CharT>
504inline typename basic_cstring<CharT>::const_iterator
505basic_cstring<CharT>::end() const
506{
507 return m_end;
508}
509
510//____________________________________________________________________________//
511
512template<typename CharT>
513inline typename basic_cstring<CharT>::size_type
514basic_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
534template<typename CharT>
535inline typename basic_cstring<CharT>::size_type
536basic_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
556template<typename CharT>
557inline basic_cstring<CharT>
558basic_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
569template<typename CharT>
570inline basic_cstring<CharT>
571basic_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
584template<typename CharT1,typename CharT2>
585inline bool
586operator==( 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
595template<typename CharT1,typename CharT2>
596inline bool
597operator==( 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
608template<typename CharT>
609inline bool
610operator==( 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
617template<typename CharT1,typename CharT2>
618inline bool
619operator==( CharT1* s2, basic_cstring<CharT2> const& s1 )
620{
621 return s1 == s2;
622}
623
624//____________________________________________________________________________//
625
626template<typename CharT>
627inline bool
628operator==( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
629{
630 return s1 == s2;
631}
632
633//____________________________________________________________________________//
634
635template<typename CharT>
636inline bool
637operator!=( basic_cstring<CharT> const& s1, CharT* s2 )
638{
639 return !(s1 == s2);
640}
641
642//____________________________________________________________________________//
643
644template<typename CharT>
645inline bool
646operator!=( CharT* s2, basic_cstring<CharT> const& s1 )
647{
648 return !(s1 == s2);
649}
650
651//____________________________________________________________________________//
652
653template<typename CharT>
654inline bool
655operator!=( basic_cstring<CharT> const& s1, basic_cstring<CharT> const& s2 )
656{
657 return !(s1 == s2);
658}
659
660//____________________________________________________________________________//
661
662template<typename CharT>
663inline bool
664operator!=( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
665{
666 return !(s1 == s2);
667}
668
669//____________________________________________________________________________//
670
671template<typename CharT>
672inline bool
673operator!=( 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
684template<typename CharT>
685inline typename basic_cstring<CharT>::value_type
686first_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
699template<typename CharT>
700inline typename basic_cstring<CharT>::value_type
701last_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
714template<typename CharT1, typename CharT2>
715inline void
716assign_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 ndnboost
726
727//____________________________________________________________________________//
728
729#include <ndnboost/test/detail/enable_warnings.hpp>
730
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700731#endif // NDNBOOST_TEST_BASIC_CSTRING_HPP_071894GER