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_CFX_STRING_C_TEMPLATE_H_
      8 #define CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_
      9 
     10 #include <algorithm>
     11 #include <type_traits>
     12 
     13 #include "core/fxcrt/fx_system.h"
     14 
     15 // An immutable string with caller-provided storage which must outlive the
     16 // string itself. These are not necessarily nul-terminated, so that substring
     17 // extraction (via the Mid(), Left(), and Right() methods) is copy-free.
     18 template <typename T>
     19 class CFX_StringCTemplate {
     20  public:
     21   using CharType = T;
     22   using UnsignedType = typename std::make_unsigned<CharType>::type;
     23 
     24   CFX_StringCTemplate() : m_Ptr(nullptr), m_Length(0) {}
     25 
     26   // Deliberately implicit to avoid calling on every string literal.
     27   // NOLINTNEXTLINE(runtime/explicit)
     28   CFX_StringCTemplate(const CharType* ptr)
     29       : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)),
     30         m_Length(ptr ? FXSYS_len(ptr) : 0) {}
     31 
     32   CFX_StringCTemplate(const CharType* ptr, FX_STRSIZE len)
     33       : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)),
     34         m_Length(len == -1 ? FXSYS_len(ptr) : len) {}
     35 
     36   template <typename U = UnsignedType>
     37   CFX_StringCTemplate(
     38       const UnsignedType* ptr,
     39       FX_STRSIZE size,
     40       typename std::enable_if<!std::is_same<U, CharType>::value>::type* = 0)
     41       : m_Ptr(ptr), m_Length(size) {}
     42 
     43   // Deliberately implicit to avoid calling on every string literal.
     44   // |ch| must be an lvalue that outlives the the CFX_StringCTemplate.
     45   // NOLINTNEXTLINE(runtime/explicit)
     46   CFX_StringCTemplate(CharType& ch) {
     47     m_Ptr = reinterpret_cast<const UnsignedType*>(&ch);
     48     m_Length = 1;
     49   }
     50 
     51   CFX_StringCTemplate(const CFX_StringCTemplate& src) {
     52     m_Ptr = src.m_Ptr;
     53     m_Length = src.m_Length;
     54   }
     55 
     56   CFX_StringCTemplate& operator=(const CharType* src) {
     57     m_Ptr = reinterpret_cast<const UnsignedType*>(src);
     58     m_Length = src ? FXSYS_len(src) : 0;
     59     return *this;
     60   }
     61 
     62   CFX_StringCTemplate& operator=(const CFX_StringCTemplate& src) {
     63     m_Ptr = src.m_Ptr;
     64     m_Length = src.m_Length;
     65     return *this;
     66   }
     67 
     68   bool operator==(const CharType* ptr) const {
     69     return FXSYS_len(ptr) == m_Length &&
     70            FXSYS_cmp(ptr, reinterpret_cast<const CharType*>(m_Ptr), m_Length) ==
     71                0;
     72   }
     73   bool operator==(const CFX_StringCTemplate& other) const {
     74     return other.m_Length == m_Length &&
     75            FXSYS_cmp(reinterpret_cast<const CharType*>(other.m_Ptr),
     76                      reinterpret_cast<const CharType*>(m_Ptr), m_Length) == 0;
     77   }
     78   bool operator!=(const CharType* ptr) const { return !(*this == ptr); }
     79   bool operator!=(const CFX_StringCTemplate& other) const {
     80     return !(*this == other);
     81   }
     82 
     83   uint32_t GetID(FX_STRSIZE start_pos = 0) const {
     84     if (m_Length == 0 || start_pos < 0 || start_pos >= m_Length)
     85       return 0;
     86 
     87     uint32_t strid = 0;
     88     FX_STRSIZE size = std::min(4, m_Length - start_pos);
     89     for (FX_STRSIZE i = 0; i < size; i++)
     90       strid = strid * 256 + m_Ptr[start_pos + i];
     91 
     92     return strid << ((4 - size) * 8);
     93   }
     94 
     95   const UnsignedType* raw_str() const { return m_Ptr; }
     96   const CharType* c_str() const {
     97     return reinterpret_cast<const CharType*>(m_Ptr);
     98   }
     99 
    100   FX_STRSIZE GetLength() const { return m_Length; }
    101   bool IsEmpty() const { return m_Length == 0; }
    102 
    103   UnsignedType GetAt(FX_STRSIZE index) const { return m_Ptr[index]; }
    104   CharType CharAt(FX_STRSIZE index) const {
    105     return static_cast<CharType>(m_Ptr[index]);
    106   }
    107 
    108   FX_STRSIZE Find(CharType ch) const {
    109     const UnsignedType* found = reinterpret_cast<const UnsignedType*>(
    110         FXSYS_chr(reinterpret_cast<const CharType*>(m_Ptr), ch, m_Length));
    111     return found ? found - m_Ptr : -1;
    112   }
    113 
    114   CFX_StringCTemplate Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const {
    115     index = std::max(0, index);
    116     if (index > m_Length)
    117       return CFX_StringCTemplate();
    118 
    119     if (count < 0 || count > m_Length - index)
    120       count = m_Length - index;
    121 
    122     return CFX_StringCTemplate(m_Ptr + index, count);
    123   }
    124 
    125   CFX_StringCTemplate Left(FX_STRSIZE count) const {
    126     if (count <= 0)
    127       return CFX_StringCTemplate();
    128 
    129     return CFX_StringCTemplate(m_Ptr, std::min(count, m_Length));
    130   }
    131 
    132   CFX_StringCTemplate Right(FX_STRSIZE count) const {
    133     if (count <= 0)
    134       return CFX_StringCTemplate();
    135 
    136     count = std::min(count, m_Length);
    137     return CFX_StringCTemplate(m_Ptr + m_Length - count, count);
    138   }
    139 
    140   const UnsignedType& operator[](size_t index) const { return m_Ptr[index]; }
    141 
    142   bool operator<(const CFX_StringCTemplate& that) const {
    143     int result = FXSYS_cmp(reinterpret_cast<const CharType*>(m_Ptr),
    144                            reinterpret_cast<const CharType*>(that.m_Ptr),
    145                            std::min(m_Length, that.m_Length));
    146     return result < 0 || (result == 0 && m_Length < that.m_Length);
    147   }
    148 
    149  protected:
    150   const UnsignedType* m_Ptr;
    151   FX_STRSIZE m_Length;
    152 
    153  private:
    154   void* operator new(size_t) throw() { return nullptr; }
    155 };
    156 
    157 template <typename T>
    158 inline bool operator==(const T* lhs, const CFX_StringCTemplate<T>& rhs) {
    159   return rhs == lhs;
    160 }
    161 
    162 template <typename T>
    163 inline bool operator!=(const T* lhs, const CFX_StringCTemplate<T>& rhs) {
    164   return rhs != lhs;
    165 }
    166 
    167 extern template class CFX_StringCTemplate<FX_CHAR>;
    168 extern template class CFX_StringCTemplate<FX_WCHAR>;
    169 
    170 #endif  // CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_
    171