xref: /aosp_15_r20/external/pigweed/pw_allocator/public/pw_allocator/layout.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <cstddef>
17 
18 #include "pw_assert/assert.h"
19 #include "pw_preprocessor/compiler.h"
20 #include "pw_result/result.h"
21 
22 namespace pw::allocator {
23 
24 /// Describes the layout of a block of memory.
25 ///
26 /// Layouts are passed to allocators, and consist of a (possibly padded) size
27 /// and a power-of-two alignment no larger than the size. Layouts can be
28 /// constructed for a type `T` using `Layout::Of`.
29 ///
30 /// Example:
31 ///
32 /// @code{.cpp}
33 ///    struct MyStruct {
34 ///      uint8_t field1[3];
35 ///      uint32_t field2[3];
36 ///    };
37 ///    constexpr Layout layout_for_struct = Layout::Of<MyStruct>();
38 /// @endcode
39 class Layout {
40  public:
Layout()41   constexpr Layout() : Layout(0) {}
Layout(size_t size)42   constexpr explicit Layout(size_t size)
43       : Layout(size, alignof(std::max_align_t)) {}
Layout(size_t size,size_t alignment)44   constexpr Layout(size_t size, size_t alignment)
45       : size_(size), alignment_(alignment) {}
46 
47   /// Creates a Layout for the given type.
48   template <typename T>
Of()49   static constexpr Layout Of() {
50     return Layout(sizeof(T), alignof(T));
51   }
52 
53   /// If the result is okay, returns its contained layout; otherwise, returns a
54   /// default layout.
Unwrap(const Result<Layout> & result)55   static constexpr Layout Unwrap(const Result<Layout>& result) {
56     return result.ok() ? (*result) : Layout();
57   }
58 
Extend(size_t size)59   constexpr Layout Extend(size_t size) const {
60     PW_ASSERT(!PW_ADD_OVERFLOW(size, size_, &size));
61     return Layout(size, alignment_);
62   }
63 
size()64   constexpr size_t size() const { return size_; }
alignment()65   constexpr size_t alignment() const { return alignment_; }
66 
67  private:
68   size_t size_;
69   size_t alignment_;
70 };
71 
72 inline bool operator==(const Layout& lhs, const Layout& rhs) {
73   return lhs.size() == rhs.size() && lhs.alignment() == rhs.alignment();
74 }
75 
76 inline bool operator!=(const Layout& lhs, const Layout& rhs) {
77   return !(lhs == rhs);
78 }
79 
80 }  // namespace pw::allocator
81