• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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