aboutsummaryrefslogtreecommitdiff
path: root/core/fxcrt/string_data_template.cpp
blob: 6e750075bec949646281f969b984bd458a86df46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright 2020 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

#include "core/fxcrt/string_data_template.h"

#include <string.h>

#include <new>

#include "core/fxcrt/fx_memory.h"
#include "core/fxcrt/fx_safe_types.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"

namespace fxcrt {

// static
template <typename CharType>
StringDataTemplate<CharType>* StringDataTemplate<CharType>::Create(
    size_t nLen) {
  DCHECK_GT(nLen, 0);

  // Calculate space needed for the fixed portion of the struct plus the
  // NUL char that is not included in |m_nAllocLength|.
  int overhead = offsetof(StringDataTemplate, m_String) + sizeof(CharType);
  FX_SAFE_SIZE_T nSize = nLen;
  nSize *= sizeof(CharType);
  nSize += overhead;

  // Now round to an 16-byte boundary, assuming the underlying allocator is most
  // likely PartitionAlloc, which has 16 byte chunks. This will help with cases
  // where we can save a re-alloc when adding a few characters to a string by
  // using this otherwise wasted space.
  nSize += 15;
  nSize &= ~15;
  size_t totalSize = nSize.ValueOrDie();
  size_t usableLen = (totalSize - overhead) / sizeof(CharType);
  DCHECK(usableLen >= nLen);

  void* pData = FX_StringAlloc(char, totalSize);
  return new (pData) StringDataTemplate(nLen, usableLen);
}

// static
template <typename CharType>
StringDataTemplate<CharType>* StringDataTemplate<CharType>::Create(
    const CharType* pStr,
    size_t nLen) {
  StringDataTemplate* result = Create(nLen);
  result->CopyContents(pStr, nLen);
  return result;
}

template <typename CharType>
void StringDataTemplate<CharType>::Release() {
  if (--m_nRefs <= 0)
    FX_Free(this);
}

template <typename CharType>
void StringDataTemplate<CharType>::CopyContents(
    const StringDataTemplate& other) {
  DCHECK(other.m_nDataLength <= m_nAllocLength);
  memcpy(m_String, other.m_String,
         (other.m_nDataLength + 1) * sizeof(CharType));
}

template <typename CharType>
void StringDataTemplate<CharType>::CopyContents(const CharType* pStr,
                                                size_t nLen) {
  DCHECK_GE(nLen, 0);
  DCHECK_LE(nLen, m_nAllocLength);
  memcpy(m_String, pStr, nLen * sizeof(CharType));
  m_String[nLen] = 0;
}

template <typename CharType>
void StringDataTemplate<CharType>::CopyContentsAt(size_t offset,
                                                  const CharType* pStr,
                                                  size_t nLen) {
  DCHECK_GE(offset, 0);
  DCHECK_GE(nLen, 0);
  DCHECK_LE(offset + nLen, m_nAllocLength);
  memcpy(m_String + offset, pStr, nLen * sizeof(CharType));
  m_String[offset + nLen] = 0;
}

template <typename CharType>
StringDataTemplate<CharType>::StringDataTemplate(size_t dataLen,
                                                 size_t allocLen)
    : m_nDataLength(dataLen), m_nAllocLength(allocLen) {
  DCHECK_GE(dataLen, 0);
  DCHECK_LE(dataLen, allocLen);
  m_String[dataLen] = 0;
}

template class StringDataTemplate<char>;
template class StringDataTemplate<wchar_t>;

}  // namespace fxcrt