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