• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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 <cstdint>
17 
18 #include "pw_log_tokenized/config.h"
19 
20 namespace pw {
21 namespace log_tokenized {
22 namespace internal {
23 
24 // Internal class for managing the metadata bit fields.
25 template <typename T, unsigned kBits, unsigned kShift>
26 struct BitField {
27  public:
GetBitField28   static constexpr T Get(T value) { return (value >> kShift) & kMask; }
ShiftBitField29   static constexpr T Shift(T value) {
30     return (value <= kMask ? value : T(0)) << kShift;
31   }
32 
33  private:
34   static constexpr T kMask = (T(1) << kBits) - 1;
35 };
36 
37 template <typename T, unsigned kShift>
38 class BitField<T, 0, kShift> {
39  public:
Get(T)40   static constexpr T Get(T) { return 0; }
Shift(T)41   static constexpr T Shift(T) { return 0; }
42 };
43 
44 // This class, which is aliased to pw::log_tokenized::Metadata below, is used to
45 // access the log metadata packed into the tokenizer's payload argument.
46 template <unsigned kLevelBits,
47           unsigned kLineBits,
48           unsigned kFlagBits,
49           unsigned kModuleBits,
50           typename T = uintptr_t>
51 class GenericMetadata {
52  public:
53   template <T log_level = 0, T module = 0, T flags = 0, T line = 0>
Set()54   static constexpr GenericMetadata Set() {
55     static_assert(log_level < (1 << kLevelBits), "The level is too large!");
56     static_assert(line < (1 << kLineBits), "The line number is too large!");
57     static_assert(flags < (1 << kFlagBits), "The flags are too large!");
58     static_assert(module < (1 << kModuleBits), "The module is too large!");
59 
60     return GenericMetadata(Level::Shift(log_level) | Module::Shift(module) |
61                            Flags::Shift(flags) | Line::Shift(line));
62   }
63 
GenericMetadata(T value)64   constexpr GenericMetadata(T value) : bits_(value) {}
65 
66   // The log level of this message.
level()67   constexpr T level() const { return Level::Get(bits_); }
68 
69   // The line number of the log call. The first line in a file is 1. If the line
70   // number is 0, it was too large to be stored.
line_number()71   constexpr T line_number() const { return Line::Get(bits_); }
72 
73   // The flags provided to the log call.
flags()74   constexpr T flags() const { return Flags::Get(bits_); }
75 
76   // The 16 bit tokenized version of the module name (PW_LOG_MODULE_NAME).
module()77   constexpr T module() const { return Module::Get(bits_); }
78 
79  private:
80   using Level = BitField<T, kLevelBits, 0>;
81   using Line = BitField<T, kLineBits, kLevelBits>;
82   using Flags = BitField<T, kFlagBits, kLevelBits + kLineBits>;
83   using Module = BitField<T, kModuleBits, kLevelBits + kLineBits + kFlagBits>;
84 
85   T bits_;
86 
87   static_assert(kLevelBits + kLineBits + kFlagBits + kModuleBits <=
88                 sizeof(bits_) * 8);
89 };
90 
91 }  // namespace internal
92 
93 using Metadata = internal::GenericMetadata<PW_LOG_TOKENIZED_LEVEL_BITS,
94                                            PW_LOG_TOKENIZED_LINE_BITS,
95                                            PW_LOG_TOKENIZED_FLAG_BITS,
96                                            PW_LOG_TOKENIZED_MODULE_BITS>;
97 
98 }  // namespace log_tokenized
99 }  // namespace pw
100