Chromium Code Reviews| Index: core/fxcrt/cfx_string_c_template.h |
| diff --git a/core/fxcrt/cfx_string_c_template.h b/core/fxcrt/cfx_string_c_template.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..70b9fcd6094405c832164f6c4142a07942f63dc2 |
| --- /dev/null |
| +++ b/core/fxcrt/cfx_string_c_template.h |
| @@ -0,0 +1,168 @@ |
| +// Copyright 2016 PDFium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| + |
| +#ifndef CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ |
| +#define CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ |
| + |
| +#include <algorithm> |
| +#include <type_traits> |
| + |
| +#include "core/fxcrt/include/fx_system.h" |
| + |
| +// An immutable string with caller-provided storage which must outlive the |
| +// string itself. These are not necessarily nul-terminated, so that substring |
| +// extraction (via the Mid(), Left(), and Right() methods) is copy-free. |
| +template <typename T> |
| +class CFX_StringCTemplate { |
| + public: |
| + using CharType = T; |
|
Lei Zhang
2016/05/13 20:47:40
Can you just use:
template <typename CharType>
o
Tom Sepez
2016/05/13 21:20:16
No, there are places where we want to have CFX_Byt
|
| + using UnsignedType = typename std::make_unsigned<CharType>::type; |
| + |
| + CFX_StringCTemplate() : m_Ptr(nullptr), m_Length(0) {} |
| + |
| + // Deliberately implicit to avoid calling on every string literal. |
| + CFX_StringCTemplate(const CharType* ptr) |
| + : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)), |
| + m_Length(ptr ? FXSYS_len(ptr) : 0) {} |
| + |
| + CFX_StringCTemplate(const CharType* ptr, FX_STRSIZE len) |
| + : m_Ptr(reinterpret_cast<const UnsignedType*>(ptr)), |
| + m_Length(len == -1 ? FXSYS_len(ptr) : len) {} |
| + |
| + template <typename U = UnsignedType> |
| + CFX_StringCTemplate( |
| + const UnsignedType* ptr, |
| + FX_STRSIZE size, |
| + typename std::enable_if<!std::is_same<U, CharType>::value>::type* = 0) |
| + : m_Ptr(ptr), m_Length(size) {} |
| + |
| + // Deliberately implicit to avoid calling on every string literal. |
| + // |ch| must be an lvalue that outlives the the CFX_StringCTemplate. |
| + CFX_StringCTemplate(CharType& ch) { |
| + m_Ptr = reinterpret_cast<const UnsignedType*>(&ch); |
| + m_Length = 1; |
| + } |
| + |
| + CFX_StringCTemplate(const CFX_StringCTemplate& src) { |
| + m_Ptr = src.m_Ptr; |
| + m_Length = src.m_Length; |
| + } |
| + |
| + CFX_StringCTemplate& operator=(const CharType* src) { |
| + m_Ptr = reinterpret_cast<const UnsignedType*>(src); |
| + m_Length = src ? FXSYS_len(src) : 0; |
| + return *this; |
| + } |
| + |
| + CFX_StringCTemplate& operator=(const CFX_StringCTemplate& src) { |
| + m_Ptr = src.m_Ptr; |
| + m_Length = src.m_Length; |
| + return *this; |
| + } |
| + |
| + bool operator==(const CharType* ptr) const { |
| + return FXSYS_len(ptr) == m_Length && |
| + FXSYS_cmp(ptr, reinterpret_cast<const CharType*>(m_Ptr), m_Length) == |
| + 0; |
| + } |
| + bool operator==(const CFX_StringCTemplate& other) const { |
| + return other.m_Length == m_Length && |
| + FXSYS_cmp(reinterpret_cast<const CharType*>(other.m_Ptr), |
| + reinterpret_cast<const CharType*>(m_Ptr), m_Length) == 0; |
| + } |
| + bool operator!=(const CharType* ptr) const { return !(*this == ptr); } |
| + bool operator!=(const CFX_StringCTemplate& other) const { |
| + return !(*this == other); |
| + } |
| + |
| + uint32_t GetID(FX_STRSIZE start_pos = 0) const { |
| + if (m_Length == 0 || start_pos < 0 || start_pos >= m_Length) |
| + return 0; |
| + |
| + uint32_t strid = 0; |
| + FX_STRSIZE size = std::min(4, m_Length - start_pos); |
| + for (FX_STRSIZE i = 0; i < size; i++) |
| + strid = strid * 256 + m_Ptr[start_pos + i]; |
| + |
| + return strid << ((4 - size) * 8); |
| + } |
| + |
| + const UnsignedType* raw_str() const { return m_Ptr; } |
| + const CharType* c_str() const { |
| + return reinterpret_cast<const CharType*>(m_Ptr); |
| + } |
| + |
| + FX_STRSIZE GetLength() const { return m_Length; } |
| + bool IsEmpty() const { return m_Length == 0; } |
| + |
| + UnsignedType GetAt(FX_STRSIZE index) const { return m_Ptr[index]; } |
| + CharType CharAt(FX_STRSIZE index) const { |
| + return static_cast<CharType>(m_Ptr[index]); |
| + } |
| + |
| + FX_STRSIZE Find(CharType ch) const { |
| + const UnsignedType* found = reinterpret_cast<const UnsignedType*>( |
| + FXSYS_chr(reinterpret_cast<const CharType*>(m_Ptr), ch, m_Length)); |
| + return found ? found - m_Ptr : -1; |
| + } |
| + |
| + CFX_StringCTemplate Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const { |
| + index = std::max(0, index); |
| + if (index > m_Length) |
| + return CFX_StringCTemplate(); |
| + |
| + if (count < 0 || count > m_Length - index) |
| + count = m_Length - index; |
| + |
| + return CFX_StringCTemplate(m_Ptr + index, count); |
| + } |
| + |
| + CFX_StringCTemplate Left(FX_STRSIZE count) const { |
| + if (count <= 0) |
| + return CFX_StringCTemplate(); |
| + |
| + return CFX_StringCTemplate(m_Ptr, std::min(count, m_Length)); |
| + } |
| + |
| + CFX_StringCTemplate Right(FX_STRSIZE count) const { |
| + if (count <= 0) |
| + return CFX_StringCTemplate(); |
| + |
| + count = std::min(count, m_Length); |
| + return CFX_StringCTemplate(m_Ptr + m_Length - count, count); |
| + } |
| + |
| + const UnsignedType& operator[](size_t index) const { return m_Ptr[index]; } |
| + |
| + bool operator<(const CFX_StringCTemplate& that) const { |
| + int result = FXSYS_cmp(reinterpret_cast<const CharType*>(m_Ptr), |
| + reinterpret_cast<const CharType*>(that.m_Ptr), |
| + std::min(m_Length, that.m_Length)); |
| + return result < 0 || (result == 0 && m_Length < that.m_Length); |
| + } |
| + |
| + protected: |
| + const UnsignedType* m_Ptr; |
| + FX_STRSIZE m_Length; |
| + |
| + private: |
| + void* operator new(size_t) throw() { return nullptr; } |
| +}; |
| + |
| +template <typename T> |
| +inline bool operator==(const T* lhs, const CFX_StringCTemplate<T>& rhs) { |
| + return rhs == lhs; |
| +} |
| + |
| +template <typename T> |
| +inline bool operator!=(const T* lhs, const CFX_StringCTemplate<T>& rhs) { |
| + return rhs != lhs; |
| +} |
| + |
| +extern template class CFX_StringCTemplate<FX_CHAR>; |
| +extern template class CFX_StringCTemplate<FX_WCHAR>; |
| + |
| +#endif // CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ |