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