• 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_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 
CFX_StringCTemplate()24   CFX_StringCTemplate() : m_Ptr(nullptr), m_Length(0) {}
25 
26   // Deliberately implicit to avoid calling on every string literal.
27   // NOLINTNEXTLINE(runtime/explicit)
CFX_StringCTemplate(const CharType * ptr)28   CFX_StringCTemplate(const CharType* ptr)
29       : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)),
30         m_Length(ptr ? FXSYS_len(ptr) : 0) {}
31 
CFX_StringCTemplate(const CharType * ptr,FX_STRSIZE len)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)
m_Ptr(ptr)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)
CFX_StringCTemplate(CharType & ch)46   CFX_StringCTemplate(CharType& ch) {
47     m_Ptr = reinterpret_cast<const UnsignedType*>(&ch);
48     m_Length = 1;
49   }
50 
CFX_StringCTemplate(const CFX_StringCTemplate & src)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 
raw_str()95   const UnsignedType* raw_str() const { return m_Ptr; }
c_str()96   const CharType* c_str() const {
97     return reinterpret_cast<const CharType*>(m_Ptr);
98   }
99 
GetLength()100   FX_STRSIZE GetLength() const { return m_Length; }
IsEmpty()101   bool IsEmpty() const { return m_Length == 0; }
102 
GetAt(FX_STRSIZE index)103   UnsignedType GetAt(FX_STRSIZE index) const { return m_Ptr[index]; }
CharAt(FX_STRSIZE index)104   CharType CharAt(FX_STRSIZE index) const {
105     return static_cast<CharType>(m_Ptr[index]);
106   }
107 
Find(CharType ch)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 
Left(FX_STRSIZE count)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 
Right(FX_STRSIZE count)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:
new(size_t)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