1 /* 2 * Copyright 2016 Two Blue Cubes Ltd. All rights reserved. 3 * 4 * Distributed under the Boost Software License, Version 1.0. (See accompanying 5 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 */ 7 #ifndef CATCH_STRINGREF_H_INCLUDED 8 #define CATCH_STRINGREF_H_INCLUDED 9 10 #include <cstddef> 11 #include <string> 12 #include <iosfwd> 13 14 namespace Catch { 15 16 class StringData; 17 18 /// A non-owning string class (similar to the forthcoming std::string_view) 19 /// Note that, because a StringRef may be a substring of another string, 20 /// it may not be null terminated. c_str() must return a null terminated 21 /// string, however, and so the StringRef will internally take ownership 22 /// (taking a copy), if necessary. In theory this ownership is not externally 23 /// visible - but it does mean (substring) StringRefs should not be shared between 24 /// threads. 25 class StringRef { 26 public: 27 using size_type = std::size_t; 28 29 private: 30 friend struct StringRefTestAccess; 31 32 char const* m_start; 33 size_type m_size; 34 35 char* m_data = nullptr; 36 37 void takeOwnership(); 38 39 static constexpr char const* const s_empty = ""; 40 41 public: // construction/ assignment StringRef()42 StringRef() noexcept 43 : StringRef( s_empty, 0 ) 44 {} 45 StringRef(StringRef const & other)46 StringRef( StringRef const& other ) noexcept 47 : m_start( other.m_start ), 48 m_size( other.m_size ) 49 {} 50 StringRef(StringRef && other)51 StringRef( StringRef&& other ) noexcept 52 : m_start( other.m_start ), 53 m_size( other.m_size ), 54 m_data( other.m_data ) 55 { 56 other.m_data = nullptr; 57 } 58 59 StringRef( char const* rawChars ) noexcept; 60 StringRef(char const * rawChars,size_type size)61 StringRef( char const* rawChars, size_type size ) noexcept 62 : m_start( rawChars ), 63 m_size( size ) 64 {} 65 StringRef(std::string const & stdString)66 StringRef( std::string const& stdString ) noexcept 67 : m_start( stdString.c_str() ), 68 m_size( stdString.size() ) 69 {} 70 ~StringRef()71 ~StringRef() noexcept { 72 delete[] m_data; 73 } 74 75 auto operator = ( StringRef const &other ) noexcept -> StringRef& { 76 delete[] m_data; 77 m_data = nullptr; 78 m_start = other.m_start; 79 m_size = other.m_size; 80 return *this; 81 } 82 83 operator std::string() const; 84 85 void swap( StringRef& other ) noexcept; 86 87 public: // operators 88 auto operator == ( StringRef const& other ) const noexcept -> bool; 89 auto operator != ( StringRef const& other ) const noexcept -> bool; 90 91 auto operator[] ( size_type index ) const noexcept -> char; 92 93 public: // named queries 94 auto empty() const noexcept -> bool { 95 return m_size == 0; 96 } 97 auto size() const noexcept -> size_type { 98 return m_size; 99 } 100 101 auto numberOfCharacters() const noexcept -> size_type; 102 auto c_str() const -> char const*; 103 104 public: // substrings and searches 105 auto substr( size_type start, size_type size ) const noexcept -> StringRef; 106 107 // Returns the current start pointer. 108 // Note that the pointer can change when if the StringRef is a substring 109 auto currentData() const noexcept -> char const*; 110 111 private: // ownership queries - may not be consistent between calls 112 auto isOwned() const noexcept -> bool; 113 auto isSubstring() const noexcept -> bool; 114 }; 115 116 auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; 117 auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; 118 auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; 119 120 auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; 121 auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; 122 123 124 inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { 125 return StringRef( rawChars, size ); 126 } 127 128 } // namespace Catch 129 130 #endif // CATCH_STRINGREF_H_INCLUDED 131