1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "recording/mem_allocator.h"
17
18 #include "securec.h"
19 #include "utils/log.h"
20
21 namespace OHOS {
22 namespace Rosen {
23 namespace Drawing {
24 namespace {
25 constexpr size_t LARGE_MALLOC = 200000000;
26 }
27 static constexpr size_t MEM_SIZE_MAX = SIZE_MAX;
28
MemAllocator()29 MemAllocator::MemAllocator() : isReadOnly_(false), capacity_(0), size_(0), startPtr_(nullptr) {}
30
~MemAllocator()31 MemAllocator::~MemAllocator()
32 {
33 Clear();
34 }
35
BuildFromData(const void * data,size_t size)36 bool MemAllocator::BuildFromData(const void* data, size_t size)
37 {
38 if (!data || size == 0 || size > MEM_SIZE_MAX) {
39 return false;
40 }
41
42 Clear();
43 isReadOnly_ = true;
44 startPtr_ = const_cast<char*>(static_cast<const char*>(data));
45 capacity_ = size;
46 size_ = size;
47
48 return true;
49 }
50
BuildFromDataWithCopy(const void * data,size_t size)51 bool MemAllocator::BuildFromDataWithCopy(const void* data, size_t size)
52 {
53 if (!data || size == 0 || size > MEM_SIZE_MAX) {
54 return false;
55 }
56
57 Clear();
58 isReadOnly_ = false;
59 Add(data, size);
60
61 return true;
62 }
63
Clear()64 void MemAllocator::Clear()
65 {
66 if (!isReadOnly_ && startPtr_) {
67 delete[] startPtr_;
68 }
69 isReadOnly_ = true;
70 startPtr_ = nullptr;
71 capacity_ = 0;
72 size_ = 0;
73 }
74
ClearData()75 void MemAllocator::ClearData()
76 {
77 if (!isReadOnly_ && startPtr_) {
78 delete[] startPtr_;
79 }
80 startPtr_ = nullptr;
81 capacity_ = 0;
82 size_ = 0;
83 }
84
Resize(size_t size)85 bool MemAllocator::Resize(size_t size)
86 {
87 if (isReadOnly_ || size == 0 || size > MEM_SIZE_MAX || size < size_) {
88 return false;
89 }
90 if (size > LARGE_MALLOC) {
91 LOGW("MemAllocator::Resize this time malloc large memory, size:%{public}zu", size);
92 }
93 char* newData = new char[size];
94 if (!newData) {
95 return false;
96 }
97
98 if (startPtr_) {
99 if (!memcpy_s(newData, size, startPtr_, size_)) {
100 delete[] startPtr_;
101 } else {
102 delete[] newData;
103 return false;
104 }
105 }
106 startPtr_ = newData;
107 capacity_ = size;
108 return true;
109 }
110
Add(const void * data,size_t size)111 void* MemAllocator::Add(const void* data, size_t size)
112 {
113 if (isReadOnly_ || !data || size == 0 || size > MEM_SIZE_MAX) {
114 return nullptr;
115 }
116
117 if (capacity_ == 0 || capacity_ - size_ < size) {
118 // The capacity is not enough, expand the capacity
119 if (Resize((capacity_ + size) * MEMORY_EXPANSION_FACTOR) == false) {
120 return nullptr;
121 }
122 }
123 if (!memcpy_s(startPtr_ + size_, capacity_ - size_, data, size)) {
124 size_ += size;
125 return startPtr_ + size_ - size;
126 } else {
127 return nullptr;
128 }
129 }
130
GetSize() const131 size_t MemAllocator::GetSize() const
132 {
133 return size_;
134 }
135
GetData() const136 const void* MemAllocator::GetData() const
137 {
138 return startPtr_;
139 }
140
AddrToOffset(const void * addr) const141 uint32_t MemAllocator::AddrToOffset(const void* addr) const
142 {
143 if (!addr) {
144 return 0;
145 }
146
147 auto offset = static_cast<uint32_t>(static_cast<const char*>(addr) - startPtr_);
148 if (offset > size_) {
149 return 0;
150 }
151 return offset;
152 }
153
OffsetToAddr(size_t offset) const154 void* MemAllocator::OffsetToAddr(size_t offset) const
155 {
156 if (offset >= size_) {
157 return nullptr;
158 }
159
160 return static_cast<void*>(startPtr_ + offset);
161 }
162 } // namespace Drawing
163 } // namespace Rosen
164 } // namespace OHOS
165