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 8 9 #if defined(__clang__) 10 # pragma clang diagnostic push 11 # pragma clang diagnostic ignored "-Wexit-time-destructors" 12 #endif 13 14 #include "catch_stringref.h" 15 16 #include <ostream> 17 #include <cstring> 18 #include <cstdint> 19 20 namespace { 21 const uint32_t byte_2_lead = 0xC0; 22 const uint32_t byte_3_lead = 0xE0; 23 const uint32_t byte_4_lead = 0xF0; 24 } 25 26 namespace Catch { StringRef(char const * rawChars)27 StringRef::StringRef( char const* rawChars ) noexcept 28 : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) ) 29 {} 30 operator std::string() const31 StringRef::operator std::string() const { 32 return std::string( m_start, m_size ); 33 } 34 swap(StringRef & other)35 void StringRef::swap( StringRef& other ) noexcept { 36 std::swap( m_start, other.m_start ); 37 std::swap( m_size, other.m_size ); 38 std::swap( m_data, other.m_data ); 39 } 40 c_str() const41 auto StringRef::c_str() const -> char const* { 42 if( isSubstring() ) 43 const_cast<StringRef*>( this )->takeOwnership(); 44 return m_start; 45 } currentData() const46 auto StringRef::currentData() const noexcept -> char const* { 47 return m_start; 48 } 49 isOwned() const50 auto StringRef::isOwned() const noexcept -> bool { 51 return m_data != nullptr; 52 } isSubstring() const53 auto StringRef::isSubstring() const noexcept -> bool { 54 return m_start[m_size] != '\0'; 55 } 56 takeOwnership()57 void StringRef::takeOwnership() { 58 if( !isOwned() ) { 59 m_data = new char[m_size+1]; 60 memcpy( m_data, m_start, m_size ); 61 m_data[m_size] = '\0'; 62 m_start = m_data; 63 } 64 } substr(size_type start,size_type size) const65 auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { 66 if( start < m_size ) 67 return StringRef( m_start+start, size ); 68 else 69 return StringRef(); 70 } operator ==(StringRef const & other) const71 auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { 72 return 73 size() == other.size() && 74 (std::strncmp( m_start, other.m_start, size() ) == 0); 75 } operator !=(StringRef const & other) const76 auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { 77 return !operator==( other ); 78 } 79 operator [](size_type index) const80 auto StringRef::operator[](size_type index) const noexcept -> char { 81 return m_start[index]; 82 } 83 numberOfCharacters() const84 auto StringRef::numberOfCharacters() const noexcept -> size_type { 85 size_type noChars = m_size; 86 // Make adjustments for uft encodings 87 for( size_type i=0; i < m_size; ++i ) { 88 char c = m_start[i]; 89 if( ( c & byte_2_lead ) == byte_2_lead ) { 90 noChars--; 91 if (( c & byte_3_lead ) == byte_3_lead ) 92 noChars--; 93 if( ( c & byte_4_lead ) == byte_4_lead ) 94 noChars--; 95 } 96 } 97 return noChars; 98 } 99 operator +(StringRef const & lhs,StringRef const & rhs)100 auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string { 101 std::string str; 102 str.reserve( lhs.size() + rhs.size() ); 103 str += lhs; 104 str += rhs; 105 return str; 106 } operator +(StringRef const & lhs,const char * rhs)107 auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string { 108 return std::string( lhs ) + std::string( rhs ); 109 } operator +(char const * lhs,StringRef const & rhs)110 auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string { 111 return std::string( lhs ) + std::string( rhs ); 112 } 113 operator <<(std::ostream & os,StringRef const & str)114 auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { 115 return os.write(str.currentData(), str.size()); 116 } 117 operator +=(std::string & lhs,StringRef const & rhs)118 auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { 119 lhs.append(rhs.currentData(), rhs.size()); 120 return lhs; 121 } 122 123 } // namespace Catch 124 125 #if defined(__clang__) 126 # pragma clang diagnostic pop 127 #endif 128