blob: e84ff5cf2bef28be06029557d5830946e7d49849 [file] [log] [blame]
// Copyright 2016 The PDFium Authors
// 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_STRING_DATA_TEMPLATE_H_
#define CORE_FXCRT_STRING_DATA_TEMPLATE_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/span.h"
namespace fxcrt {
template <typename CharType>
class StringDataTemplate {
public:
static RetainPtr<StringDataTemplate> Create(size_t nLen);
static RetainPtr<StringDataTemplate> Create(pdfium::span<const CharType> str);
void Retain() { ++m_nRefs; }
void Release();
bool CanOperateInPlace(size_t nTotalLen) const {
return m_nRefs <= 1 && nTotalLen <= m_nAllocLength;
}
void CopyContents(const StringDataTemplate& other);
void CopyContents(pdfium::span<const CharType> str);
void CopyContentsAt(size_t offset, pdfium::span<const CharType> str);
pdfium::span<CharType> span() {
// SAFETY: m_nDataLength is within m_String.
return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nDataLength));
}
pdfium::span<const CharType> span() const {
// SAFETY: m_nDataLength is within m_String.
return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nDataLength));
}
// Only a const-form is provided to preclude modifying the terminator.
pdfium::span<const CharType> span_with_terminator() const {
// SAFETY: m_nDataLength is within m_String and there is always a
// terminator character following it.
return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nDataLength + 1));
}
pdfium::span<CharType> alloc_span() {
// SAFETY: m_nAllocLength is within m_String.
return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nAllocLength));
}
pdfium::span<const CharType> alloc_span() const {
// SAFETY: m_nAllocLength is within m_String.
return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nAllocLength));
}
// Includes the terminating NUL not included in lengths.
pdfium::span<CharType> capacity_span() {
// SAFETY: m_nAllocLength + 1 is within m_String.
return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nAllocLength + 1));
}
pdfium::span<const CharType> capacity_span() const {
// SAFETY: m_nAllocLength + 1 is within m_String.
return UNSAFE_BUFFERS(pdfium::make_span(m_String, m_nAllocLength + 1));
}
// Return length as determined by the location of the first embedded NUL.
size_t GetStringLength() const {
return std::char_traits<CharType>::length(m_String);
}
// Unlike std::string::front(), this is always safe and returns a
// NUL char when the string is empty.
CharType Front() const { return !span().empty() ? span().front() : 0; }
// Unlike std::string::back(), this is always safe and returns a
// NUL char when the string is empty.
CharType Back() const { return !span().empty() ? span().back() : 0; }
// To ensure ref counts do not overflow, consider the worst possible case:
// the entire address space contains nothing but pointers to this object.
// Since the count increments with each new pointer, the largest value is
// the number of pointers that can fit into the address space. The size of
// the address space itself is a good upper bound on it.
intptr_t m_nRefs = 0;
// These lengths are in terms of number of characters, not bytes, and do not
// include the terminating NUL character, but the underlying buffer is sized
// to be capable of holding it.
size_t m_nDataLength;
const size_t m_nAllocLength;
// Not really 1, variable size.
CharType m_String[1];
private:
StringDataTemplate(size_t dataLen, size_t allocLen);
~StringDataTemplate() = delete;
};
extern template class StringDataTemplate<char>;
extern template class StringDataTemplate<wchar_t>;
} // namespace fxcrt
using fxcrt::StringDataTemplate;
#endif // CORE_FXCRT_STRING_DATA_TEMPLATE_H_