Home | History | Annotate | Download | only in fxcrt
      1 // Copyright 2017 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_WIDESTRING_H_
      8 #define CORE_FXCRT_WIDESTRING_H_
      9 
     10 #include <functional>
     11 #include <iterator>
     12 #include <utility>
     13 
     14 #include "core/fxcrt/fx_memory.h"
     15 #include "core/fxcrt/fx_system.h"
     16 #include "core/fxcrt/retain_ptr.h"
     17 #include "core/fxcrt/string_data_template.h"
     18 #include "core/fxcrt/string_view_template.h"
     19 #include "third_party/base/optional.h"
     20 
     21 
     22 namespace fxcrt {
     23 
     24 class ByteString;
     25 class StringPool_WideString_Test;
     26 class WideString_ConcatInPlace_Test;
     27 
     28 // A mutable string with shared buffers using copy-on-write semantics that
     29 // avoids the cost of std::string's iterator stability guarantees.
     30 class WideString {
     31  public:
     32   using CharType = wchar_t;
     33   using const_iterator = const CharType*;
     34   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
     35 
     36   static WideString Format(const wchar_t* lpszFormat, ...) WARN_UNUSED_RESULT;
     37   static WideString FormatV(const wchar_t* lpszFormat,
     38                             va_list argList) WARN_UNUSED_RESULT;
     39 
     40   WideString();
     41   WideString(const WideString& other);
     42   WideString(WideString&& other) noexcept;
     43 
     44   // Deliberately implicit to avoid calling on every string literal.
     45   // NOLINTNEXTLINE(runtime/explicit)
     46   WideString(wchar_t ch);
     47   // NOLINTNEXTLINE(runtime/explicit)
     48   WideString(const wchar_t* ptr);
     49 
     50   // No implicit conversions from byte strings.
     51   // NOLINTNEXTLINE(runtime/explicit)
     52   WideString(char) = delete;
     53 
     54   WideString(const wchar_t* ptr, size_t len);
     55 
     56   explicit WideString(const WideStringView& str);
     57   WideString(const WideStringView& str1, const WideStringView& str2);
     58   WideString(const std::initializer_list<WideStringView>& list);
     59 
     60   ~WideString();
     61 
     62   static WideString FromLocal(const ByteStringView& str) WARN_UNUSED_RESULT;
     63   static WideString FromCodePage(const ByteStringView& str,
     64                                  uint16_t codepage) WARN_UNUSED_RESULT;
     65 
     66   static WideString FromUTF8(const ByteStringView& str) WARN_UNUSED_RESULT;
     67   static WideString FromUTF16LE(const unsigned short* str,
     68                                 size_t len) WARN_UNUSED_RESULT;
     69 
     70   static size_t WStringLength(const unsigned short* str) WARN_UNUSED_RESULT;
     71 
     72   // Explicit conversion to C-style wide string.
     73   // Note: Any subsequent modification of |this| will invalidate the result.
     74   const wchar_t* c_str() const { return m_pData ? m_pData->m_String : L""; }
     75 
     76   // Explicit conversion to WideStringView.
     77   // Note: Any subsequent modification of |this| will invalidate the result.
     78   WideStringView AsStringView() const {
     79     return WideStringView(c_str(), GetLength());
     80   }
     81 
     82   // Note: Any subsequent modification of |this| will invalidate iterators.
     83   const_iterator begin() const { return m_pData ? m_pData->m_String : nullptr; }
     84   const_iterator end() const {
     85     return m_pData ? m_pData->m_String + m_pData->m_nDataLength : nullptr;
     86   }
     87 
     88   // Note: Any subsequent modification of |this| will invalidate iterators.
     89   const_reverse_iterator rbegin() const {
     90     return const_reverse_iterator(end());
     91   }
     92   const_reverse_iterator rend() const {
     93     return const_reverse_iterator(begin());
     94   }
     95 
     96   void clear() { m_pData.Reset(); }
     97 
     98   size_t GetLength() const { return m_pData ? m_pData->m_nDataLength : 0; }
     99   size_t GetStringLength() const {
    100     return m_pData ? wcslen(m_pData->m_String) : 0;
    101   }
    102   bool IsEmpty() const { return !GetLength(); }
    103   bool IsValidIndex(size_t index) const { return index < GetLength(); }
    104   bool IsValidLength(size_t length) const { return length <= GetLength(); }
    105 
    106   const WideString& operator=(const wchar_t* str);
    107   const WideString& operator=(const WideString& stringSrc);
    108   const WideString& operator=(const WideStringView& stringSrc);
    109 
    110   const WideString& operator+=(const wchar_t* str);
    111   const WideString& operator+=(wchar_t ch);
    112   const WideString& operator+=(const WideString& str);
    113   const WideString& operator+=(const WideStringView& str);
    114 
    115   bool operator==(const wchar_t* ptr) const;
    116   bool operator==(const WideStringView& str) const;
    117   bool operator==(const WideString& other) const;
    118 
    119   bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); }
    120   bool operator!=(const WideStringView& str) const { return !(*this == str); }
    121   bool operator!=(const WideString& other) const { return !(*this == other); }
    122 
    123   bool operator<(const wchar_t* ptr) const;
    124   bool operator<(const WideStringView& str) const;
    125   bool operator<(const WideString& other) const;
    126 
    127   CharType operator[](const size_t index) const {
    128     ASSERT(IsValidIndex(index));
    129     return m_pData ? m_pData->m_String[index] : 0;
    130   }
    131 
    132   CharType First() const { return GetLength() ? (*this)[0] : 0; }
    133   CharType Last() const { return GetLength() ? (*this)[GetLength() - 1] : 0; }
    134 
    135   void SetAt(size_t index, wchar_t c);
    136 
    137   int Compare(const wchar_t* str) const;
    138   int Compare(const WideString& str) const;
    139   int CompareNoCase(const wchar_t* str) const;
    140 
    141   WideString Mid(size_t first, size_t count) const;
    142   WideString Left(size_t count) const;
    143   WideString Right(size_t count) const;
    144 
    145   size_t Insert(size_t index, wchar_t ch);
    146   size_t InsertAtFront(wchar_t ch) { return Insert(0, ch); }
    147   size_t InsertAtBack(wchar_t ch) { return Insert(GetLength(), ch); }
    148   size_t Delete(size_t index, size_t count = 1);
    149 
    150   void MakeLower();
    151   void MakeUpper();
    152 
    153   void Trim();
    154   void Trim(wchar_t target);
    155   void Trim(const WideStringView& targets);
    156 
    157   void TrimLeft();
    158   void TrimLeft(wchar_t target);
    159   void TrimLeft(const WideStringView& targets);
    160 
    161   void TrimRight();
    162   void TrimRight(wchar_t target);
    163   void TrimRight(const WideStringView& targets);
    164 
    165   void Reserve(size_t len);
    166   wchar_t* GetBuffer(size_t len);
    167   void ReleaseBuffer(size_t len);
    168 
    169   int GetInteger() const;
    170   float GetFloat() const;
    171 
    172   Optional<size_t> Find(const WideStringView& pSub, size_t start = 0) const;
    173   Optional<size_t> Find(wchar_t ch, size_t start = 0) const;
    174 
    175   bool Contains(const WideStringView& lpszSub, size_t start = 0) const {
    176     return Find(lpszSub, start).has_value();
    177   }
    178 
    179   bool Contains(char ch, size_t start = 0) const {
    180     return Find(ch, start).has_value();
    181   }
    182 
    183   size_t Replace(const WideStringView& pOld, const WideStringView& pNew);
    184   size_t Remove(wchar_t ch);
    185 
    186   ByteString UTF8Encode() const;
    187 
    188   // This method will add \0\0 to the end of the string to represent the
    189   // wide string terminator. These values are in the string, not just the data,
    190   // so GetLength() will include them.
    191   ByteString UTF16LE_Encode() const;
    192 
    193  protected:
    194   using StringData = StringDataTemplate<wchar_t>;
    195 
    196   void ReallocBeforeWrite(size_t nLen);
    197   void AllocBeforeWrite(size_t nLen);
    198   void AllocCopy(WideString& dest, size_t nCopyLen, size_t nCopyIndex) const;
    199   void AssignCopy(const wchar_t* pSrcData, size_t nSrcLen);
    200   void Concat(const wchar_t* lpszSrcData, size_t nSrcLen);
    201 
    202   RetainPtr<StringData> m_pData;
    203 
    204   friend WideString_ConcatInPlace_Test;
    205   friend StringPool_WideString_Test;
    206 };
    207 
    208 inline WideString operator+(const WideStringView& str1,
    209                             const WideStringView& str2) {
    210   return WideString(str1, str2);
    211 }
    212 inline WideString operator+(const WideStringView& str1, const wchar_t* str2) {
    213   return WideString(str1, str2);
    214 }
    215 inline WideString operator+(const wchar_t* str1, const WideStringView& str2) {
    216   return WideString(str1, str2);
    217 }
    218 inline WideString operator+(const WideStringView& str1, wchar_t ch) {
    219   return WideString(str1, WideStringView(ch));
    220 }
    221 inline WideString operator+(wchar_t ch, const WideStringView& str2) {
    222   return WideString(ch, str2);
    223 }
    224 inline WideString operator+(const WideString& str1, const WideString& str2) {
    225   return WideString(str1.AsStringView(), str2.AsStringView());
    226 }
    227 inline WideString operator+(const WideString& str1, wchar_t ch) {
    228   return WideString(str1.AsStringView(), WideStringView(ch));
    229 }
    230 inline WideString operator+(wchar_t ch, const WideString& str2) {
    231   return WideString(ch, str2.AsStringView());
    232 }
    233 inline WideString operator+(const WideString& str1, const wchar_t* str2) {
    234   return WideString(str1.AsStringView(), str2);
    235 }
    236 inline WideString operator+(const wchar_t* str1, const WideString& str2) {
    237   return WideString(str1, str2.AsStringView());
    238 }
    239 inline WideString operator+(const WideString& str1,
    240                             const WideStringView& str2) {
    241   return WideString(str1.AsStringView(), str2);
    242 }
    243 inline WideString operator+(const WideStringView& str1,
    244                             const WideString& str2) {
    245   return WideString(str1, str2.AsStringView());
    246 }
    247 inline bool operator==(const wchar_t* lhs, const WideString& rhs) {
    248   return rhs == lhs;
    249 }
    250 inline bool operator==(const WideStringView& lhs, const WideString& rhs) {
    251   return rhs == lhs;
    252 }
    253 inline bool operator!=(const wchar_t* lhs, const WideString& rhs) {
    254   return rhs != lhs;
    255 }
    256 inline bool operator!=(const WideStringView& lhs, const WideString& rhs) {
    257   return rhs != lhs;
    258 }
    259 inline bool operator<(const wchar_t* lhs, const WideString& rhs) {
    260   return rhs.Compare(lhs) > 0;
    261 }
    262 
    263 std::wostream& operator<<(std::wostream& os, const WideString& str);
    264 std::ostream& operator<<(std::ostream& os, const WideString& str);
    265 std::wostream& operator<<(std::wostream& os, const WideStringView& str);
    266 std::ostream& operator<<(std::ostream& os, const WideStringView& str);
    267 
    268 }  // namespace fxcrt
    269 
    270 using WideString = fxcrt::WideString;
    271 
    272 uint32_t FX_HashCode_GetW(const WideStringView& str, bool bIgnoreCase);
    273 
    274 namespace std {
    275 
    276 template <>
    277 struct hash<WideString> {
    278   std::size_t operator()(const WideString& str) const {
    279     return FX_HashCode_GetW(str.AsStringView(), false);
    280   }
    281 };
    282 
    283 }  // namespace std
    284 
    285 extern template struct std::hash<WideString>;
    286 
    287 #endif  // CORE_FXCRT_WIDESTRING_H_
    288