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