1 /*
2  * Copyright (c) 2024 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_CUSTOM_PAINT_CANVAS_PAINT_MEM_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_CUSTOM_PAINT_CANVAS_PAINT_MEM_H
18 
19 #include <cstdlib>
20 #include <limits>
21 #include <memory>
22 #include <type_traits>
23 #include <utility>
24 
25 #include "base/log/log.h"
26 
27 namespace OHOS::Ace::NG {
28 
29 template <typename T,
30           typename = std::enable_if_t<std::is_trivially_default_constructible<T>::value &&
31                                       std::is_trivially_destructible<T>::value>>
32 class AutoTMalloc {
33 public:
34     explicit AutoTMalloc(T* ptr = nullptr) : fPtr_(ptr) {}
AutoTMalloc(size_t count)35     explicit AutoTMalloc(size_t count)
36         : fPtr_(count ? (T*)MallocThrow(count, sizeof(T)) : nullptr) {}
37 
38     AutoTMalloc(AutoTMalloc&&) = default;
39     AutoTMalloc& operator=(AutoTMalloc&&) = default;
realloc(size_t count)40     void realloc(size_t count)
41     {
42         fPtr_.reset(count ? (T*)ReallocThrow(fPtr_.release(), count * sizeof(T)) : nullptr);
43     }
44 
45     T* Reset(size_t count = 0)
46     {
47         fPtr_.reset(count ? (T*)MallocThrow(count, sizeof(T)) : nullptr);
48         return this->get();
49     }
get()50     T* get() const { return fPtr_.get(); }
51     operator T*() { return fPtr_.get(); }
52     operator const T*() const { return fPtr_.get(); }
53     T& operator[](int index) { return fPtr_.get()[index]; }
54     const T& operator[](int index) const { return fPtr_.get()[index]; }
data()55     const T* data() const { return fPtr_.get(); }
data()56     T* data() { return fPtr_.get(); }
release()57     T* release() { return fPtr_.release(); }
58 
59 private:
60     enum {
61         MALLOC_ZERO_INITIALIZE   = 1 << 0,
62         MALLOC_THROW             = 1 << 1,
63     };
64 
ThrowOnFailure(size_t size,void * p)65     static inline void* ThrowOnFailure(size_t size, void* p)
66     {
67         if (size > 0 && p == nullptr) {
68             TAG_LOGE(AceLogTag::ACE_CANVAS_COMPONENT, "canvas paint out of memory");
69         }
70         return p;
71     }
72 
Add(size_t x,size_t y)73     static inline size_t Add(size_t x, size_t y)
74     {
75         return x + y;
76     }
77 
Mul32(uint32_t x,uint32_t y)78     static inline uint32_t Mul32(uint32_t x, uint32_t y)
79     {
80         uint64_t bx = x;
81         uint64_t by = y;
82         uint64_t result = bx * by;
83         return result;
84     }
85 
Mul64(uint64_t x,uint64_t y)86     static inline uint64_t Mul64(uint64_t x, uint64_t y)
87     {
88         if (x <= std::numeric_limits<uint64_t>::max() >> INT32SIZE
89             && y <= std::numeric_limits<uint64_t>::max() >> INT32SIZE) {
90             return x * y;
91         } else {
92             auto hi = [](uint64_t x) { return x >> INT32SIZE; };
93             auto lo = [](uint64_t x) { return x & INT32VALUE; };
94             uint64_t lx_ly = lo(x) * lo(y);
95             uint64_t hx_ly = hi(x) * lo(y);
96             uint64_t lx_hy = lo(x) * hi(y);
97             uint64_t result = Add(lx_ly, (hx_ly << INT32SIZE));
98             result = Add(result, (lx_hy << INT32SIZE));
99             return result;
100         }
101     }
102 
MallocFlags(size_t size,unsigned flags)103     static inline void* MallocFlags(size_t size, unsigned flags)
104     {
105         void* p;
106         if (flags & MALLOC_ZERO_INITIALIZE) {
107             p = std::calloc(size, 1);
108         } else {
109             p = std::malloc(size);
110         }
111         if (flags & MALLOC_THROW) {
112             return ThrowOnFailure(size, p);
113         } else {
114             return p;
115         }
116     }
117 
MallocThrow(size_t x,size_t y)118     static inline void* MallocThrow(size_t x, size_t y)
119     {
120         auto size = sizeof(size_t) == sizeof(uint64_t)? Mul64(x, y): Mul32(x, y);
121         return MallocFlags(size, MALLOC_THROW);
122     }
123 
ReallocThrow(void * addr,size_t size)124     static inline void* ReallocThrow(void*addr, size_t size)
125     {
126         return nullptr;
127     }
128 
129     template <typename V, V* P>
130     struct FunctionWrapper {
131         template <typename... Args>
132         auto operator()(Args&&... args) const-> decltype(P(std::forward<Args>(args)...))
133         {
134             return P(std::forward<Args>(args)...);
135         }
136     };
137 
138     std::unique_ptr<T, FunctionWrapper<void(void*),  free>> fPtr_;
139     static constexpr uint32_t INT32SIZE = 32;
140     static constexpr uint32_t INT32VALUE = 0xFFFFFFFF;
141 };
142 
143 } // namespce OHOS::Ace
144 
145 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_CUSTOM_PAINT_CANVAS_PAINT_MEM_H
146