1 // Copyright 2016 The PDFium Authors 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_STRING_DATA_TEMPLATE_H_ 8 #define CORE_FXCRT_STRING_DATA_TEMPLATE_H_ 9 10 #include <stddef.h> 11 #include <stdint.h> 12 13 #include <string> 14 15 #include "core/fxcrt/retain_ptr.h" 16 #include "core/fxcrt/span.h" 17 18 namespace fxcrt { 19 20 template <typename CharType> 21 class StringDataTemplate { 22 public: 23 static RetainPtr<StringDataTemplate> Create(size_t nLen); 24 static RetainPtr<StringDataTemplate> Create(pdfium::span<const CharType> str); 25 Retain()26 void Retain() { ++m_nRefs; } 27 void Release(); 28 CanOperateInPlace(size_t nTotalLen)29 bool CanOperateInPlace(size_t nTotalLen) const { 30 return m_nRefs <= 1 && nTotalLen <= m_nAllocLength; 31 } 32 33 void CopyContents(const StringDataTemplate& other); 34 void CopyContents(pdfium::span<const CharType> str); 35 void CopyContentsAt(size_t offset, pdfium::span<const CharType> str); 36 span()37 pdfium::span<CharType> span() { 38 // SAFETY: m_nDataLength is within m_String. 39 return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nDataLength)); 40 } span()41 pdfium::span<const CharType> span() const { 42 // SAFETY: m_nDataLength is within m_String. 43 return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nDataLength)); 44 } 45 46 // Only a const-form is provided to preclude modifying the terminator. span_with_terminator()47 pdfium::span<const CharType> span_with_terminator() const { 48 // SAFETY: m_nDataLength is within m_String and there is always a 49 // terminator character following it. 50 return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nDataLength + 1)); 51 } 52 alloc_span()53 pdfium::span<CharType> alloc_span() { 54 // SAFETY: m_nAllocLength is within m_String. 55 return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nAllocLength)); 56 } alloc_span()57 pdfium::span<const CharType> alloc_span() const { 58 // SAFETY: m_nAllocLength is within m_String. 59 return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nAllocLength)); 60 } 61 62 // Includes the terminating NUL not included in lengths. capacity_span()63 pdfium::span<CharType> capacity_span() { 64 // SAFETY: m_nAllocLength + 1 is within m_String. 65 return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nAllocLength + 1)); 66 } capacity_span()67 pdfium::span<const CharType> capacity_span() const { 68 // SAFETY: m_nAllocLength + 1 is within m_String. 69 return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nAllocLength + 1)); 70 } 71 72 // Return length as determined by the location of the first embedded NUL. GetStringLength()73 size_t GetStringLength() const { 74 return std::char_traits<CharType>::length(m_String); 75 } 76 77 // Unlike std::string::front(), this is always safe and returns a 78 // NUL char when the string is empty. Front()79 CharType Front() const { return !span().empty() ? span().front() : 0; } 80 81 // Unlike std::string::back(), this is always safe and returns a 82 // NUL char when the string is empty. Back()83 CharType Back() const { return !span().empty() ? span().back() : 0; } 84 85 // To ensure ref counts do not overflow, consider the worst possible case: 86 // the entire address space contains nothing but pointers to this object. 87 // Since the count increments with each new pointer, the largest value is 88 // the number of pointers that can fit into the address space. The size of 89 // the address space itself is a good upper bound on it. 90 intptr_t m_nRefs = 0; 91 92 // These lengths are in terms of number of characters, not bytes, and do not 93 // include the terminating NUL character, but the underlying buffer is sized 94 // to be capable of holding it. 95 size_t m_nDataLength; 96 const size_t m_nAllocLength; 97 98 // Not really 1, variable size. 99 CharType m_String[1]; 100 101 private: 102 StringDataTemplate(size_t dataLen, size_t allocLen); 103 ~StringDataTemplate() = delete; 104 }; 105 106 extern template class StringDataTemplate<char>; 107 extern template class StringDataTemplate<wchar_t>; 108 109 } // namespace fxcrt 110 111 using fxcrt::StringDataTemplate; 112 113 #endif // CORE_FXCRT_STRING_DATA_TEMPLATE_H_ 114