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