• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2025 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 "pw_bloat/bloat_this_binary.h"
17 #include "pw_containers/intrusive_forward_list.h"
18 #include "pw_containers/size_report/size_report.h"
19 
20 namespace pw::containers::size_report {
21 
22 /// A simple item for intrusive forward lists that wraps a moveable value.
23 template <typename T>
24 struct ForwardListItem : public IntrusiveForwardList<ForwardListItem<T>>::Item {
25   using Base = typename IntrusiveForwardList<ForwardListItem<T>>::Item;
26 
ForwardListItemForwardListItem27   constexpr explicit ForwardListItem(T value) : value_(value) {}
28 
ForwardListItemForwardListItem29   ForwardListItem(ForwardListItem&& other) { *this = std::move(other); }
30 
31   ForwardListItem& operator=(ForwardListItem&& other) {
32     value_ = other.value_;
33     return *this;
34   }
35 
36   bool operator<(const ForwardListItem& rhs) const {
37     return value_ < rhs.value_;
38   }
39 
40   bool operator==(const ForwardListItem& rhs) const {
41     return value_ == rhs.value_;
42   }
43 
44   T value_;
45 };
46 
47 /// Invokes methods of the pw::IntrusiveForwardList type.
48 ///
49 /// This method is used both to measure intrusive forward lists directly, as
50 /// well as to provide a baseline for measuring other types that use intrusive
51 /// forward lists and want to only measure their contributions to code size.
52 template <typename ItemType, int&... kExplicitGuard, typename Iterator>
MeasureIntrusiveForwardList(Iterator first,Iterator last,uint32_t mask)53 int MeasureIntrusiveForwardList(Iterator first, Iterator last, uint32_t mask) {
54   mask = SetBaseline(mask);
55   auto& list1 = GetContainer<IntrusiveForwardList<ItemType>>();
56   IntrusiveForwardList<ItemType> list2;
57   auto iter1 = first;
58   for (size_t i = 0; i < 3; ++i) {
59     if (iter1 != last) {
60       ++iter1;
61     }
62   }
63   list1.assign(first, iter1);
64   list2.assign(iter1, last);
65 
66   auto& item1 = list1.front();
67   PW_BLOAT_EXPR(list1.pop_front(), mask);
68   PW_BLOAT_EXPR(list2.push_front(item1), mask);
69   if constexpr (std::is_move_assignable_v<ItemType>) {
70     PW_BLOAT_EXPR(list1.swap(list2), mask);
71     PW_BLOAT_EXPR(list1.reverse(), mask);
72   }
73   if constexpr (internal::is_weakly_orderable_v<ItemType>) {
74     PW_BLOAT_EXPR(list1.sort(), mask);
75     PW_BLOAT_EXPR(list1.merge(list2), mask);
76     PW_BLOAT_COND(list1.unique() != 0, mask);
77   }
78   PW_BLOAT_EXPR(list2.clear(), mask);
79   PW_BLOAT_EXPR(list1.remove(item1), mask);
80 
81   ItemType& item2 = list1.front();
82   auto iter2 = list1.erase_after(list1.before_begin());
83   PW_BLOAT_EXPR(list1.insert_after(iter2, item2), mask);
84   PW_BLOAT_EXPR(list1.splice_after(list1.begin(), list2), mask);
85 
86   return list1.empty() ? 1 : 0;
87 }
88 
89 }  // namespace pw::containers::size_report
90