C/C++ API Reference
Loading...
Searching...
No Matches
result.h
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#include <cstdint>
18
19#include "pw_allocator/hardening.h"
20#include "pw_assert/assert.h"
21#include "pw_status/status.h"
22#include "pw_status/status_with_size.h"
23
24namespace pw::allocator {
25namespace internal {
26
33 public:
36 enum class Prev : uint8_t {
37 kUnchanged,
38 kSplitNew,
39 kResizedSmaller,
40 kResizedLarger,
41 };
42
45 enum class Next : uint8_t {
46 kUnchanged,
47 kSplitNew,
48 kResized,
49 kMerged,
50 };
51
52 [[nodiscard]] constexpr Prev prev() const {
53 return static_cast<Prev>(Decode(kPrevBits, kPrevShift));
54 }
55
56 [[nodiscard]] constexpr Next next() const {
57 return static_cast<Next>(Decode(kNextBits, kNextShift));
58 }
59
60 [[nodiscard]] constexpr size_t size() const {
61 return Decode(kSizeBits, kSizeShift);
62 }
63
64 [[nodiscard]] constexpr bool ok() const { return encoded_.ok(); }
65
66 [[nodiscard]] constexpr Status status() const { return encoded_.status(); }
67
70 constexpr void IgnoreUnlessStrict() const;
71
72 protected:
73 constexpr GenericBlockResult(Status status,
74 Prev prev,
75 Next next,
76 size_t size);
77
78 private:
79 static constexpr size_t kPrevBits = 5;
80 static constexpr size_t kPrevShift = 0;
81
82 static constexpr size_t kNextBits = 5;
83 static constexpr size_t kNextShift = kPrevBits;
84
85 static constexpr size_t kSizeBits = 10;
86 static constexpr size_t kSizeShift = kPrevBits + kNextBits;
87
88 static constexpr size_t Encode(size_t value, size_t bits, size_t shift);
89 constexpr size_t Decode(size_t bits, size_t shift) const;
90
91 StatusWithSize encoded_;
92};
93
94} // namespace internal
95
97
105template <typename BlockType>
106class [[nodiscard]] BlockResult : public internal::GenericBlockResult {
107 public:
108 constexpr explicit BlockResult(BlockType* block)
109 : BlockResult(block, OkStatus()) {}
110
111 constexpr BlockResult(BlockType* block, Status status)
113 status, Prev::kUnchanged, Next::kUnchanged, 0),
114 block_(block) {}
115
116 constexpr BlockResult(BlockType* block, Prev prev)
117 : BlockResult(block, prev, Next::kUnchanged, 0) {}
118
119 constexpr BlockResult(BlockType* block, Prev prev, size_t shifted_to_prev)
120 : BlockResult(block, prev, Next::kUnchanged, shifted_to_prev) {}
121
122 constexpr BlockResult(BlockType* block, Next next)
123 : BlockResult(block, Prev::kUnchanged, next, 0) {}
124
125 constexpr BlockResult(BlockType* block, Prev prev, Next next)
126 : BlockResult(block, prev, next, 0) {}
127
128 constexpr BlockResult(BlockType* block,
129 Prev prev,
130 Next next,
131 size_t shifted_to_prev);
132
133 [[nodiscard]] constexpr BlockType* block() const { return block_; }
134
135 private:
136 BlockType* block_ = nullptr;
137};
138
140
141// Template and inline method implementations.
142
143namespace internal {
144
146 if constexpr (Hardening::kIncludesDebugChecks) {
147 PW_ASSERT(ok());
148 }
149}
150
151constexpr GenericBlockResult::GenericBlockResult(Status status,
152 Prev prev,
153 Next next,
154 size_t size)
155 : encoded_(status,
156 Encode(size_t(prev), kPrevBits, kPrevShift) |
157 Encode(size_t(next), kNextBits, kNextShift) |
158 Encode(size, kSizeBits, kSizeShift)) {}
159
160constexpr size_t GenericBlockResult::Encode(size_t value,
161 size_t bits,
162 size_t shift) {
163 if constexpr (Hardening::kIncludesDebugChecks) {
164 PW_ASSERT(value < (1U << bits));
165 }
166 return value << shift;
167}
168
169constexpr size_t GenericBlockResult::Decode(size_t bits, size_t shift) const {
170 return (encoded_.size() >> shift) & ~(~static_cast<size_t>(0) << bits);
171}
172
173} // namespace internal
174
175template <typename BlockType>
176constexpr BlockResult<BlockType>::BlockResult(BlockType* block,
177 Prev prev,
178 Next next,
179 size_t shifted_to_prev)
180 : internal::GenericBlockResult(OkStatus(), prev, next, shifted_to_prev),
181 block_(block) {
182 if constexpr (Hardening::kIncludesDebugChecks) {
183 block->CheckInvariants();
184 }
185}
186
187} // namespace pw::allocator
Definition: status.h:120
constexpr bool ok() const
True if status() == OkStatus().
Definition: status_with_size.h:154
constexpr size_t size() const
Definition: status_with_size.h:148
Definition: result.h:106
constexpr void IgnoreUnlessStrict() const
Definition: result.h:145
constexpr Status OkStatus()
Definition: status.h:450