From f7036ba5884b9829fcb17aea4f3a16831abb7516 Mon Sep 17 00:00:00 2001 From: tsepez Date: Fri, 13 May 2016 15:02:43 -0700 Subject: Templatize CFX_{Byte,Wide}StringC Review-Url: https://codereview.chromium.org/1874773002 --- BUILD.gn | 1 + core/fxcrt/cfx_string_c_template.h | 168 +++++++++++++++++++++++++ core/fxcrt/fx_basic_bstring.cpp | 21 +--- core/fxcrt/fx_basic_wstring.cpp | 1 + core/fxcrt/include/fx_string.h | 249 ++----------------------------------- core/fxcrt/include/fx_system.h | 25 ++++ pdfium.gyp | 1 + testing/fx_string_testhelpers.cpp | 2 +- 8 files changed, 205 insertions(+), 263 deletions(-) create mode 100644 core/fxcrt/cfx_string_c_template.h diff --git a/BUILD.gn b/BUILD.gn index 1d87424f97..30fd1e04f3 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -593,6 +593,7 @@ config("fxge_warnings") { static_library("fxcrt") { sources = [ + "core/fxcrt/cfx_string_c_template.h", "core/fxcrt/cfx_string_data_template.h", "core/fxcrt/extension.h", "core/fxcrt/fx_basic_array.cpp", diff --git a/core/fxcrt/cfx_string_c_template.h b/core/fxcrt/cfx_string_c_template.h new file mode 100644 index 0000000000..70b9fcd609 --- /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 +#include + +#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 +class CFX_StringCTemplate { + public: + using CharType = T; + using UnsignedType = typename std::make_unsigned::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(ptr)), + m_Length(ptr ? FXSYS_len(ptr) : 0) {} + + CFX_StringCTemplate(const CharType* ptr, FX_STRSIZE len) + : m_Ptr(reinterpret_cast(ptr)), + m_Length(len == -1 ? FXSYS_len(ptr) : len) {} + + template + CFX_StringCTemplate( + const UnsignedType* ptr, + FX_STRSIZE size, + typename std::enable_if::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(&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(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(m_Ptr), m_Length) == + 0; + } + bool operator==(const CFX_StringCTemplate& other) const { + return other.m_Length == m_Length && + FXSYS_cmp(reinterpret_cast(other.m_Ptr), + reinterpret_cast(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(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(m_Ptr[index]); + } + + FX_STRSIZE Find(CharType ch) const { + const UnsignedType* found = reinterpret_cast( + FXSYS_chr(reinterpret_cast(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(m_Ptr), + reinterpret_cast(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 +inline bool operator==(const T* lhs, const CFX_StringCTemplate& rhs) { + return rhs == lhs; +} + +template +inline bool operator!=(const T* lhs, const CFX_StringCTemplate& rhs) { + return rhs != lhs; +} + +extern template class CFX_StringCTemplate; +extern template class CFX_StringCTemplate; + +#endif // CORE_FXCRT_CFX_STRING_C_TEMPLATE_H_ diff --git a/core/fxcrt/fx_basic_bstring.cpp b/core/fxcrt/fx_basic_bstring.cpp index e035dd53d1..3a81e41920 100644 --- a/core/fxcrt/fx_basic_bstring.cpp +++ b/core/fxcrt/fx_basic_bstring.cpp @@ -13,6 +13,7 @@ #include "third_party/base/numerics/safe_math.h" template class CFX_StringDataTemplate; +template class CFX_StringCTemplate; namespace { @@ -931,26 +932,6 @@ void CFX_ByteString::TrimLeft() { uint32_t CFX_ByteString::GetID(FX_STRSIZE start_pos) const { return AsStringC().GetID(start_pos); } -uint32_t CFX_ByteStringC::GetID(FX_STRSIZE start_pos) const { - if (m_Length == 0) { - return 0; - } - if (start_pos < 0 || start_pos >= m_Length) { - return 0; - } - uint32_t strid = 0; - if (start_pos + 4 > m_Length) { - for (FX_STRSIZE i = 0; i < m_Length - start_pos; i++) { - strid = strid * 256 + m_Ptr[start_pos + i]; - } - strid = strid << ((4 - m_Length + start_pos) * 8); - } else { - for (int i = 0; i < 4; i++) { - strid = strid * 256 + m_Ptr[start_pos + i]; - } - } - return strid; -} FX_STRSIZE FX_ftoa(FX_FLOAT d, FX_CHAR* buf) { buf[0] = '0'; buf[1] = '\0'; diff --git a/core/fxcrt/fx_basic_wstring.cpp b/core/fxcrt/fx_basic_wstring.cpp index 03cb0599d5..8c1d494e7a 100644 --- a/core/fxcrt/fx_basic_wstring.cpp +++ b/core/fxcrt/fx_basic_wstring.cpp @@ -14,6 +14,7 @@ #include "third_party/base/numerics/safe_math.h" template class CFX_StringDataTemplate; +template class CFX_StringCTemplate; namespace { diff --git a/core/fxcrt/include/fx_string.h b/core/fxcrt/include/fx_string.h index 617e02ee5a..9019522eca 100644 --- a/core/fxcrt/include/fx_string.h +++ b/core/fxcrt/include/fx_string.h @@ -10,6 +10,7 @@ #include // For intptr_t. #include +#include "core/fxcrt/cfx_string_c_template.h" #include "core/fxcrt/cfx_string_data_template.h" #include "core/fxcrt/include/cfx_retain_ptr.h" #include "core/fxcrt/include/fx_memory.h" @@ -18,134 +19,20 @@ class CFX_ByteString; class CFX_WideString; -// 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() method) is copy-free. -class CFX_ByteStringC { - public: - typedef FX_CHAR value_type; - - CFX_ByteStringC() { - m_Ptr = NULL; - m_Length = 0; - } - - CFX_ByteStringC(const uint8_t* ptr, FX_STRSIZE size) { - m_Ptr = ptr; - m_Length = size; - } - - // Deliberately implicit to avoid calling on every string literal. - CFX_ByteStringC(const FX_CHAR* ptr) { - m_Ptr = (const uint8_t*)ptr; - m_Length = ptr ? FXSYS_strlen(ptr) : 0; - } - - // Deliberately implicit to avoid calling on every string literal. - // |ch| must be an lvalue that outlives the the CFX_ByteStringC. - CFX_ByteStringC(FX_CHAR& ch) { - m_Ptr = (const uint8_t*)&ch; - m_Length = 1; - } - - CFX_ByteStringC(const FX_CHAR* ptr, FX_STRSIZE len) { - m_Ptr = (const uint8_t*)ptr; - m_Length = (len == -1) ? FXSYS_strlen(ptr) : len; - } - - CFX_ByteStringC(const CFX_ByteStringC& src) { - m_Ptr = src.m_Ptr; - m_Length = src.m_Length; - } - - CFX_ByteStringC& operator=(const FX_CHAR* src) { - m_Ptr = (const uint8_t*)src; - m_Length = m_Ptr ? FXSYS_strlen(src) : 0; - return *this; - } - - CFX_ByteStringC& operator=(const CFX_ByteStringC& src) { - m_Ptr = src.m_Ptr; - m_Length = src.m_Length; - return *this; - } - - bool operator==(const char* ptr) const { - return FXSYS_strlen(ptr) == m_Length && - FXSYS_memcmp(ptr, m_Ptr, m_Length) == 0; - } - bool operator==(const CFX_ByteStringC& other) const { - return other.m_Length == m_Length && - FXSYS_memcmp(other.m_Ptr, m_Ptr, m_Length) == 0; - } - bool operator!=(const char* ptr) const { return !(*this == ptr); } - bool operator!=(const CFX_ByteStringC& other) const { - return !(*this == other); - } - - uint32_t GetID(FX_STRSIZE start_pos = 0) const; - - const uint8_t* raw_str() const { return m_Ptr; } - const FX_CHAR* c_str() const { - return reinterpret_cast(m_Ptr); - } - - FX_STRSIZE GetLength() const { return m_Length; } - bool IsEmpty() const { return m_Length == 0; } - - uint8_t GetAt(FX_STRSIZE index) const { return m_Ptr[index]; } - FX_CHAR CharAt(FX_STRSIZE index) const { - return static_cast(m_Ptr[index]); - } - - FX_STRSIZE Find(FX_CHAR ch) const { - const uint8_t* found = - static_cast(memchr(m_Ptr, ch, m_Length)); - return found ? found - m_Ptr : -1; - } - - CFX_ByteStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const { - if (index < 0) { - index = 0; - } - if (index > m_Length) { - return CFX_ByteStringC(); - } - if (count < 0 || count > m_Length - index) { - count = m_Length - index; - } - return CFX_ByteStringC(m_Ptr + index, count); - } +using CFX_ByteStringC = CFX_StringCTemplate; +using CFX_WideStringC = CFX_StringCTemplate; - const uint8_t& operator[](size_t index) const { return m_Ptr[index]; } - - bool operator<(const CFX_ByteStringC& that) const { - int result = memcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length)); - return result < 0 || (result == 0 && m_Length < that.m_Length); - } - - protected: - const uint8_t* m_Ptr; - FX_STRSIZE m_Length; - - private: - void* operator new(size_t) throw() { return NULL; } -}; -inline bool operator==(const char* lhs, const CFX_ByteStringC& rhs) { - return rhs == lhs; -} -inline bool operator!=(const char* lhs, const CFX_ByteStringC& rhs) { - return rhs != lhs; -} #define FXBSTR_ID(c1, c2, c3, c4) \ (((uint32_t)c1 << 24) | ((uint32_t)c2 << 16) | ((uint32_t)c3 << 8) | \ ((uint32_t)c4)) +#define FX_WSTRC(wstr) CFX_WideStringC(wstr, FX_ArraySize(wstr) - 1) + // A mutable string with shared buffers using copy-on-write semantics that // avoids the cost of std::string's iterator stability guarantees. class CFX_ByteString { public: - typedef FX_CHAR value_type; + using CharType = FX_CHAR; CFX_ByteString() {} CFX_ByteString(const CFX_ByteString& other) : m_pData(other.m_pData) {} @@ -346,133 +233,11 @@ inline CFX_ByteString operator+(const CFX_ByteStringC& str1, return CFX_ByteString(str1, str2.AsStringC()); } -class CFX_WideStringC { - public: - typedef FX_WCHAR value_type; - - CFX_WideStringC() { - m_Ptr = NULL; - m_Length = 0; - } - - // Deliberately implicit to avoid calling on every string literal. - CFX_WideStringC(const FX_WCHAR* ptr) { - m_Ptr = ptr; - m_Length = ptr ? FXSYS_wcslen(ptr) : 0; - } - - // Deliberately implicit to avoid calling on every string literal. - // |ch| must be an lvalue that outlives the the CFX_WideStringC. - CFX_WideStringC(FX_WCHAR& ch) { - m_Ptr = &ch; - m_Length = 1; - } - - CFX_WideStringC(const FX_WCHAR* ptr, FX_STRSIZE len) { - m_Ptr = ptr; - m_Length = (len == -1) ? FXSYS_wcslen(ptr) : len; - } - - CFX_WideStringC(const CFX_WideStringC& src) { - m_Ptr = src.m_Ptr; - m_Length = src.m_Length; - } - - CFX_WideStringC& operator=(const FX_WCHAR* src) { - m_Ptr = src; - m_Length = FXSYS_wcslen(src); - return *this; - } - - CFX_WideStringC& operator=(const CFX_WideStringC& src) { - m_Ptr = src.m_Ptr; - m_Length = src.m_Length; - return *this; - } - - bool operator==(const wchar_t* ptr) const { - return FXSYS_wcslen(ptr) == m_Length && wmemcmp(ptr, m_Ptr, m_Length) == 0; - } - bool operator==(const CFX_WideStringC& str) const { - return str.m_Length == m_Length && wmemcmp(str.m_Ptr, m_Ptr, m_Length) == 0; - } - bool operator!=(const wchar_t* ptr) const { return !(*this == ptr); } - bool operator!=(const CFX_WideStringC& str) const { return !(*this == str); } - - const FX_WCHAR* c_str() const { return m_Ptr; } - - FX_STRSIZE GetLength() const { return m_Length; } - bool IsEmpty() const { return m_Length == 0; } - - FX_WCHAR GetAt(FX_STRSIZE index) const { return m_Ptr[index]; } - - CFX_WideStringC Left(FX_STRSIZE count) const { - if (count < 1) { - return CFX_WideStringC(); - } - if (count > m_Length) { - count = m_Length; - } - return CFX_WideStringC(m_Ptr, count); - } - - FX_STRSIZE Find(FX_WCHAR ch) const { - const FX_WCHAR* found = - static_cast(wmemchr(m_Ptr, ch, m_Length)); - return found ? found - m_Ptr : -1; - } - - CFX_WideStringC Mid(FX_STRSIZE index, FX_STRSIZE count = -1) const { - if (index < 0) { - index = 0; - } - if (index > m_Length) { - return CFX_WideStringC(); - } - if (count < 0 || count > m_Length - index) { - count = m_Length - index; - } - return CFX_WideStringC(m_Ptr + index, count); - } - - CFX_WideStringC Right(FX_STRSIZE count) const { - if (count < 1) { - return CFX_WideStringC(); - } - if (count > m_Length) { - count = m_Length; - } - return CFX_WideStringC(m_Ptr + m_Length - count, count); - } - - const FX_WCHAR& operator[](size_t index) const { return m_Ptr[index]; } - - bool operator<(const CFX_WideStringC& that) const { - int result = wmemcmp(m_Ptr, that.m_Ptr, std::min(m_Length, that.m_Length)); - return result < 0 || (result == 0 && m_Length < that.m_Length); - } - - protected: - const FX_WCHAR* m_Ptr; - FX_STRSIZE m_Length; - - private: - void* operator new(size_t) throw() { return NULL; } -}; - -inline bool operator==(const wchar_t* lhs, const CFX_WideStringC& rhs) { - return rhs == lhs; -} -inline bool operator!=(const wchar_t* lhs, const CFX_WideStringC& rhs) { - return rhs != lhs; -} -#define FX_WSTRC(wstr) CFX_WideStringC(wstr, FX_ArraySize(wstr) - 1) - // A mutable string with shared buffers using copy-on-write semantics that // avoids the cost of std::string's iterator stability guarantees. class CFX_WideString { public: - typedef FX_WCHAR value_type; + using CharType = FX_WCHAR; CFX_WideString() {} CFX_WideString(const CFX_WideString& other) : m_pData(other.m_pData) {} diff --git a/core/fxcrt/include/fx_system.h b/core/fxcrt/include/fx_system.h index b4659d14e4..205976fb15 100644 --- a/core/fxcrt/include/fx_system.h +++ b/core/fxcrt/include/fx_system.h @@ -158,6 +158,31 @@ FXSYS_FILE* FXSYS_wfopen(const FX_WCHAR* filename, const FX_WCHAR* mode); #define FXSYS_strlen(ptr) pdfium::base::checked_cast(strlen(ptr)) #define FXSYS_wcslen(ptr) pdfium::base::checked_cast(wcslen(ptr)) +// Overloaded functions for C++ templates +inline FX_STRSIZE FXSYS_len(const FX_CHAR* ptr) { + return FXSYS_strlen(ptr); +} + +inline FX_STRSIZE FXSYS_len(const FX_WCHAR* ptr) { + return FXSYS_wcslen(ptr); +} + +inline int FXSYS_cmp(const FX_CHAR* ptr1, const FX_CHAR* ptr2, size_t len) { + return memcmp(ptr1, ptr2, len); +} + +inline int FXSYS_cmp(const FX_WCHAR* ptr1, const FX_WCHAR* ptr2, size_t len) { + return wmemcmp(ptr1, ptr2, len); +} + +inline const FX_CHAR* FXSYS_chr(const FX_CHAR* ptr, FX_CHAR ch, size_t len) { + return reinterpret_cast(memchr(ptr, ch, len)); +} + +inline const FX_WCHAR* FXSYS_chr(const FX_WCHAR* ptr, FX_WCHAR ch, size_t len) { + return wmemchr(ptr, ch, len); +} + extern "C" { #else #define FXSYS_strlen(ptr) ((FX_STRSIZE)strlen(ptr)) diff --git a/pdfium.gyp b/pdfium.gyp index 63b4011e3f..5532bc8360 100644 --- a/pdfium.gyp +++ b/pdfium.gyp @@ -615,6 +615,7 @@ 'target_name': 'fxcrt', 'type': 'static_library', 'sources': [ + 'core/fxcrt/cfx_string_c_template.h', 'core/fxcrt/cfx_string_data_template.h', 'core/fxcrt/extension.h', 'core/fxcrt/fx_basic_array.cpp', diff --git a/testing/fx_string_testhelpers.cpp b/testing/fx_string_testhelpers.cpp index b2d30f3a06..934dd680e4 100644 --- a/testing/fx_string_testhelpers.cpp +++ b/testing/fx_string_testhelpers.cpp @@ -17,7 +17,7 @@ std::ostream& output_string(std::ostream& out, const T& str) { unsigned int c = str.GetAt(i); if (c >= 0x20 && c < 0x7F) { out << static_cast(c); - } else if (sizeof(typename T::value_type) == 1) { + } else if (sizeof(typename T::CharType) == 1) { out << "\\x" << std::setw(2) << c << std::setw(0); } else if (c < 0x10000) { out << "\\u" << std::setw(4) << c << std::setw(0); -- cgit v1.2.3