1 // Copyright 2016 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #ifndef CORE_FXCRT_STRING_VIEW_TEMPLATE_H_ 8 #define CORE_FXCRT_STRING_VIEW_TEMPLATE_H_ 9 10 #include <algorithm> 11 #include <iterator> 12 #include <type_traits> 13 #include <utility> 14 #include <vector> 15 16 #include "core/fxcrt/fx_system.h" 17 #include "core/fxcrt/unowned_ptr.h" 18 #include "third_party/base/optional.h" 19 #include "third_party/base/stl_util.h" 20 21 namespace fxcrt { 22 23 // An immutable string with caller-provided storage which must outlive the 24 // string itself. These are not necessarily nul-terminated, so that substring 25 // extraction (via the Mid(), Left(), and Right() methods) is copy-free. 26 template <typename T> 27 class StringViewTemplate { 28 public: 29 using CharType = T; 30 using UnsignedType = typename std::make_unsigned<CharType>::type; 31 using const_iterator = const CharType*; 32 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 33 StringViewTemplate()34 StringViewTemplate() : m_Ptr(nullptr), m_Length(0) {} 35 36 // Deliberately implicit to avoid calling on every string literal. 37 // NOLINTNEXTLINE(runtime/explicit) StringViewTemplate(const CharType * ptr)38 StringViewTemplate(const CharType* ptr) 39 : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)), 40 m_Length(ptr ? FXSYS_len(ptr) : 0) {} 41 StringViewTemplate(const CharType * ptr,size_t len)42 StringViewTemplate(const CharType* ptr, size_t len) 43 : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)), m_Length(len) {} 44 45 template <typename U = UnsignedType> 46 StringViewTemplate( 47 const UnsignedType* ptr, 48 size_t size, 49 typename std::enable_if<!std::is_same<U, CharType>::value>::type* = 0) m_Ptr(ptr)50 : m_Ptr(ptr), m_Length(size) {} 51 52 // Deliberately implicit to avoid calling on every string literal. 53 // |ch| must be an lvalue that outlives the StringViewTemplate. 54 // NOLINTNEXTLINE(runtime/explicit) StringViewTemplate(CharType & ch)55 StringViewTemplate(CharType& ch) { 56 m_Ptr = reinterpret_cast<const UnsignedType*>(&ch); 57 m_Length = 1; 58 } 59 StringViewTemplate(const StringViewTemplate & src)60 StringViewTemplate(const StringViewTemplate& src) { 61 m_Ptr = src.m_Ptr; 62 m_Length = src.m_Length; 63 } 64 65 // Any changes to |vec| invalidate the string. StringViewTemplate(const std::vector<UnsignedType> & vec)66 explicit StringViewTemplate(const std::vector<UnsignedType>& vec) { 67 m_Length = vec.size(); 68 m_Ptr = m_Length ? vec.data() : nullptr; 69 } 70 71 StringViewTemplate& operator=(const CharType* src) { 72 m_Ptr = reinterpret_cast<const UnsignedType*>(src); 73 m_Length = src ? FXSYS_len(src) : 0; 74 return *this; 75 } 76 77 StringViewTemplate& operator=(const StringViewTemplate& src) { 78 m_Ptr = src.m_Ptr; 79 m_Length = src.m_Length; 80 return *this; 81 } 82 begin()83 const_iterator begin() const { 84 return reinterpret_cast<const CharType*>(m_Ptr.Get()); 85 } end()86 const_iterator end() const { 87 return m_Ptr ? reinterpret_cast<const CharType*>(m_Ptr.Get()) + m_Length 88 : nullptr; 89 } 90 rbegin()91 const_reverse_iterator rbegin() const { 92 return const_reverse_iterator(end()); 93 } rend()94 const_reverse_iterator rend() const { 95 return const_reverse_iterator(begin()); 96 } 97 98 bool operator==(const CharType* ptr) const { 99 return FXSYS_len(ptr) == m_Length && 100 FXSYS_cmp(ptr, reinterpret_cast<const CharType*>(m_Ptr.Get()), 101 m_Length) == 0; 102 } 103 bool operator==(const StringViewTemplate& other) const { 104 return other.m_Length == m_Length && 105 FXSYS_cmp(reinterpret_cast<const CharType*>(other.m_Ptr.Get()), 106 reinterpret_cast<const CharType*>(m_Ptr.Get()), 107 m_Length) == 0; 108 } 109 bool operator!=(const CharType* ptr) const { return !(*this == ptr); } 110 bool operator!=(const StringViewTemplate& other) const { 111 return !(*this == other); 112 } 113 GetID()114 uint32_t GetID() const { 115 if (m_Length == 0) 116 return 0; 117 118 uint32_t strid = 0; 119 size_t size = std::min(static_cast<size_t>(4), m_Length); 120 for (size_t i = 0; i < size; i++) 121 strid = strid * 256 + m_Ptr.Get()[i]; 122 123 return strid << ((4 - size) * 8); 124 } 125 raw_str()126 const UnsignedType* raw_str() const { return m_Ptr.Get(); } unterminated_c_str()127 const CharType* unterminated_c_str() const { 128 return reinterpret_cast<const CharType*>(m_Ptr.Get()); 129 } 130 GetLength()131 size_t GetLength() const { return m_Length; } IsEmpty()132 bool IsEmpty() const { return m_Length == 0; } IsValidIndex(size_t index)133 bool IsValidIndex(size_t index) const { return index < GetLength(); } IsValidLength(size_t length)134 bool IsValidLength(size_t length) const { return length <= GetLength(); } 135 136 const UnsignedType& operator[](const size_t index) const { 137 ASSERT(IsValidIndex(index)); 138 return m_Ptr.Get()[index]; 139 } 140 First()141 UnsignedType First() const { return GetLength() ? (*this)[0] : 0; } 142 Last()143 UnsignedType Last() const { 144 return GetLength() ? (*this)[GetLength() - 1] : 0; 145 } 146 CharAt(const size_t index)147 const CharType CharAt(const size_t index) const { 148 ASSERT(IsValidIndex(index)); 149 return static_cast<CharType>(m_Ptr.Get()[index]); 150 } 151 Find(CharType ch)152 Optional<size_t> Find(CharType ch) const { 153 const auto* found = reinterpret_cast<const UnsignedType*>(FXSYS_chr( 154 reinterpret_cast<const CharType*>(m_Ptr.Get()), ch, m_Length)); 155 156 return found ? Optional<size_t>(found - m_Ptr.Get()) : Optional<size_t>(); 157 } 158 Contains(CharType ch)159 bool Contains(CharType ch) const { return Find(ch).has_value(); } 160 Mid(size_t first,size_t count)161 StringViewTemplate Mid(size_t first, size_t count) const { 162 if (!m_Ptr.Get()) 163 return StringViewTemplate(); 164 165 if (!IsValidIndex(first)) 166 return StringViewTemplate(); 167 168 if (count == 0 || !IsValidLength(count)) 169 return StringViewTemplate(); 170 171 if (!IsValidIndex(first + count - 1)) 172 return StringViewTemplate(); 173 174 return StringViewTemplate(m_Ptr.Get() + first, count); 175 } 176 Left(size_t count)177 StringViewTemplate Left(size_t count) const { 178 if (count == 0 || !IsValidLength(count)) 179 return StringViewTemplate(); 180 return Mid(0, count); 181 } 182 Right(size_t count)183 StringViewTemplate Right(size_t count) const { 184 if (count == 0 || !IsValidLength(count)) 185 return StringViewTemplate(); 186 return Mid(GetLength() - count, count); 187 } 188 TrimmedRight(CharType ch)189 StringViewTemplate TrimmedRight(CharType ch) const { 190 if (IsEmpty()) 191 return StringViewTemplate(); 192 193 size_t pos = GetLength(); 194 while (pos && CharAt(pos - 1) == ch) 195 pos--; 196 197 if (pos == 0) 198 return StringViewTemplate(); 199 200 return StringViewTemplate(m_Ptr.Get(), pos); 201 } 202 203 bool operator<(const StringViewTemplate& that) const { 204 int result = FXSYS_cmp(reinterpret_cast<const CharType*>(m_Ptr.Get()), 205 reinterpret_cast<const CharType*>(that.m_Ptr.Get()), 206 std::min(m_Length, that.m_Length)); 207 return result < 0 || (result == 0 && m_Length < that.m_Length); 208 } 209 210 bool operator>(const StringViewTemplate& that) const { 211 int result = FXSYS_cmp(reinterpret_cast<const CharType*>(m_Ptr.Get()), 212 reinterpret_cast<const CharType*>(that.m_Ptr.Get()), 213 std::min(m_Length, that.m_Length)); 214 return result > 0 || (result == 0 && m_Length > that.m_Length); 215 } 216 217 protected: 218 UnownedPtr<const UnsignedType> m_Ptr; 219 size_t m_Length; 220 221 private: new(size_t)222 void* operator new(size_t) throw() { return nullptr; } 223 }; 224 225 template <typename T> 226 inline bool operator==(const T* lhs, const StringViewTemplate<T>& rhs) { 227 return rhs == lhs; 228 } 229 template <typename T> 230 inline bool operator!=(const T* lhs, const StringViewTemplate<T>& rhs) { 231 return rhs != lhs; 232 } 233 template <typename T> 234 inline bool operator<(const T* lhs, const StringViewTemplate<T>& rhs) { 235 return rhs > lhs; 236 } 237 238 extern template class StringViewTemplate<char>; 239 extern template class StringViewTemplate<wchar_t>; 240 241 using ByteStringView = StringViewTemplate<char>; 242 using WideStringView = StringViewTemplate<wchar_t>; 243 244 } // namespace fxcrt 245 246 using ByteStringView = fxcrt::ByteStringView; 247 using WideStringView = fxcrt::WideStringView; 248 249 #endif // CORE_FXCRT_STRING_VIEW_TEMPLATE_H_ 250