Home | History | Annotate | Download | only in fxcrt
      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 
     34   StringViewTemplate() : m_Ptr(nullptr), m_Length(0) {}
     35 
     36   // Deliberately implicit to avoid calling on every string literal.
     37   // NOLINTNEXTLINE(runtime/explicit)
     38   StringViewTemplate(const CharType* ptr)
     39       : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)),
     40         m_Length(ptr ? FXSYS_len(ptr) : 0) {}
     41 
     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)
     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)
     55   StringViewTemplate(CharType& ch) {
     56     m_Ptr = reinterpret_cast<const UnsignedType*>(&ch);
     57     m_Length = 1;
     58   }
     59 
     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.
     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 
     83   const_iterator begin() const {
     84     return reinterpret_cast<const CharType*>(m_Ptr.Get());
     85   }
     86   const_iterator end() const {
     87     return m_Ptr ? reinterpret_cast<const CharType*>(m_Ptr.Get()) + m_Length
     88                  : nullptr;
     89   }
     90 
     91   const_reverse_iterator rbegin() const {
     92     return const_reverse_iterator(end());
     93   }
     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 
    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 
    126   const UnsignedType* raw_str() const { return m_Ptr.Get(); }
    127   const CharType* unterminated_c_str() const {
    128     return reinterpret_cast<const CharType*>(m_Ptr.Get());
    129   }
    130 
    131   size_t GetLength() const { return m_Length; }
    132   bool IsEmpty() const { return m_Length == 0; }
    133   bool IsValidIndex(size_t index) const { return index < GetLength(); }
    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 
    141   UnsignedType First() const { return GetLength() ? (*this)[0] : 0; }
    142 
    143   UnsignedType Last() const {
    144     return GetLength() ? (*this)[GetLength() - 1] : 0;
    145   }
    146 
    147   const CharType CharAt(const size_t index) const {
    148     ASSERT(IsValidIndex(index));
    149     return static_cast<CharType>(m_Ptr.Get()[index]);
    150   }
    151 
    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 
    159   bool Contains(CharType ch) const { return Find(ch).has_value(); }
    160 
    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 
    177   StringViewTemplate Left(size_t count) const {
    178     if (count == 0 || !IsValidLength(count))
    179       return StringViewTemplate();
    180     return Mid(0, count);
    181   }
    182 
    183   StringViewTemplate Right(size_t count) const {
    184     if (count == 0 || !IsValidLength(count))
    185       return StringViewTemplate();
    186     return Mid(GetLength() - count, count);
    187   }
    188 
    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:
    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