Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_metric / metric.cc
1 // Copyright 2020 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
15 #include "pw_metric/metric.h"
16
17 #include <array>
18 #include <span>
19
20 #include "pw_log/log.h"
21 #include "pw_tokenizer/base64.h"
22
23 namespace pw::metric {
24 namespace {
25
26 template <typename T>
27 std::span<const std::byte> AsSpan(const T& t) {
28   return std::span<const std::byte>(reinterpret_cast<const std::byte*>(&t),
29                                     sizeof(t));
30 }
31
32 // A convenience class to encode a token as base64 while managing the storage.
33 // TODO(keir): Consider putting this into upstream pw_tokenizer.
34 struct Base64EncodedToken {
35   Base64EncodedToken(Token token) {
36     int encoded_size = tokenizer::PrefixedBase64Encode(AsSpan(token), data);
37     data[encoded_size] = 0;
38   }
39
40   const char* value() { return data.data(); }
41   std::array<char, 16> data;
42 };
43
44 const char* Indent(int level) {
45   static const char* kWhitespace8 = "        ";
46   level = std::min(level, 4);
47   return kWhitespace8 + 8 - 2 * level;
48 }
49
50 }  // namespace
51
52 // Enable easier registration when used as a member.
53 Metric::Metric(Token name, float value, IntrusiveList<Metric>& metrics)
54     : Metric(name, value) {
55   metrics.push_front(*this);
56 }
57 Metric::Metric(Token name, uint32_t value, IntrusiveList<Metric>& metrics)
58     : Metric(name, value) {
59   metrics.push_front(*this);
60 }
61
62 float Metric::as_float() const {
63   PW_DCHECK(is_float());
64   return float_;
65 }
66
67 uint32_t Metric::as_int() const {
68   PW_DCHECK(is_int());
69   return uint_;
70 }
71
72 void Metric::Increment(uint32_t amount) {
73   PW_DCHECK(is_int());
74   uint_ += amount;
75 }
76
77 void Metric::SetInt(uint32_t value) {
78   PW_DCHECK(is_int());
79   uint_ = value;
80 }
81
82 void Metric::SetFloat(float value) {
83   PW_DCHECK(is_float());
84   float_ = value;
85 }
86
87 void Metric::Dump(int level) {
88   Base64EncodedToken encoded_name(name());
89   const char* indent = Indent(level);
90   if (is_float()) {
91     PW_LOG_INFO("%s \"%s\": %f,", indent, encoded_name.value(), as_float());
92   } else {
93     PW_LOG_INFO("%s \"%s\": %u,",
94                 indent,
95                 encoded_name.value(),
96                 static_cast<unsigned int>(as_int()));
97   }
98 }
99
100 void Metric::Dump(IntrusiveList<Metric>& metrics, int level) {
101   for (auto& m : metrics) {
102     m.Dump(level);
103   }
104 }
105
106 Group::Group(Token name) : name_(name) {}
107
108 Group::Group(Token name, IntrusiveList<Group>& groups) : name_(name) {
109   groups.push_front(*this);
110 }
111
112 void Group::Dump(int level) {
113   Base64EncodedToken encoded_name(name());
114   const char* indent = Indent(level);
115   PW_LOG_INFO("%s \"%s\": {", indent, encoded_name.value());
116   Group::Dump(children(), level + 1);
117   Metric::Dump(metrics(), level + 1);
118   PW_LOG_INFO("%s }", indent);
119 }
120
121 void Group::Dump(IntrusiveList<Group>& groups, int level) {
122   for (auto& group : groups) {
123     group.Dump(level);
124   }
125 }
126
127 }  // namespace pw::metric