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(std::nothrow) 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 || size > MEM_SIZE_MAX - size_) {
114 return nullptr;
115 }
116 auto current = startPtr_ + size_;
117 if (auto mod = reinterpret_cast<uintptr_t>(current) % ALIGN_SIZE; mod != 0) {
118 size_ += ALIGN_SIZE - mod;
119 }
120
121 if (capacity_ == 0 || capacity_ < size_ + size) {
122 // The capacity is not enough, expand the capacity
123 if (Resize((capacity_ + size) * MEMORY_EXPANSION_FACTOR) == false) {
124 return nullptr;
125 }
126 }
127 if (!memcpy_s(startPtr_ + size_, capacity_ - size_, data, size)) {
128 size_ += size;
129 return startPtr_ + size_ - size;
130 } else {
131 return nullptr;
132 }
133 }
134
GetSize() const135 size_t MemAllocator::GetSize() const
136 {
137 return size_;
138 }
139
GetData() const140 const void* MemAllocator::GetData() const
141 {
142 return startPtr_;
143 }
144
AddrToOffset(const void * addr) const145 size_t MemAllocator::AddrToOffset(const void* addr) const
146 {
147 if (!addr) {
148 return 0;
149 }
150
151 size_t offset = static_cast<size_t>(static_cast<const char*>(addr) - startPtr_);
152 if (offset > size_) {
153 return 0;
154 }
155 return offset;
156 }
157
OffsetToAddr(size_t offset,size_t size) const158 void* MemAllocator::OffsetToAddr(size_t offset, size_t size) const
159 {
160 if (offset >= size_ || size > size_ || offset > size_ - size) {
161 LOGE("MemAllocator::OffsetToAddr return nullptr.");
162 return nullptr;
163 }
164
165 return static_cast<void*>(startPtr_ + offset);
166 }
167 } // namespace Drawing
168 } // namespace Rosen
169 } // namespace OHOS
170