• 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 <stdint.h>
17 
18 #include "pw_log_tokenized/config.h"
19 #include "pw_tokenizer/tokenize_to_global_handler_with_payload.h"
20 
21 // TODO(hepler): Remove this include.
22 #ifdef __cplusplus
23 #include "pw_log_tokenized/metadata.h"
24 #endif  // __cplusplus
25 
26 // This macro implements PW_LOG using
27 // PW_TOKENIZE_TO_GLOBAL_HANDLER_WITH_PAYLOAD or an equivalent alternate macro
28 // provided by PW_LOG_TOKENIZED_ENCODE_MESSAGE. The log level, module token, and
29 // flags are packed into the payload argument.
30 //
31 // Two strings are tokenized in this macro:
32 //
33 //   - The log format string, tokenized in the default tokenizer domain.
34 //   - PW_LOG_MODULE_NAME, masked to 16 bits and tokenized in the
35 //     "pw_log_module_names" tokenizer domain.
36 //
37 // To use this macro, implement pw_tokenizer_HandleEncodedMessageWithPayload,
38 // which is defined in pw_tokenizer/tokenize.h. The log metadata can be accessed
39 // using pw::log_tokenized::Metadata. For example:
40 //
41 //   extern "C" void pw_tokenizer_HandleEncodedMessageWithPayload(
42 //       pw_tokenizer_Payload payload, const uint8_t data[], size_t size) {
43 //     pw::log_tokenized::Metadata metadata(payload);
44 //
45 //     if (metadata.level() >= kLogLevel && ModuleEnabled(metadata.module())) {
46 //       EmitLogMessage(data, size, metadata.flags());
47 //     }
48 //   }
49 //
50 #define PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD(                     \
51     level, flags, message, ...)                                              \
52   do {                                                                       \
53     _PW_TOKENIZER_CONST uintptr_t _pw_log_tokenized_module_token =           \
54         PW_TOKENIZE_STRING_MASK("pw_log_module_names",                       \
55                                 ((1u << PW_LOG_TOKENIZED_MODULE_BITS) - 1u), \
56                                 PW_LOG_MODULE_NAME);                         \
57     const uintptr_t _pw_log_tokenized_level = level;                         \
58     PW_LOG_TOKENIZED_ENCODE_MESSAGE(                                         \
59         (_PW_LOG_TOKENIZED_LEVEL(_pw_log_tokenized_level) |                  \
60          _PW_LOG_TOKENIZED_MODULE(_pw_log_tokenized_module_token) |          \
61          _PW_LOG_TOKENIZED_FLAGS(flags) | _PW_LOG_TOKENIZED_LINE(__LINE__)), \
62         PW_LOG_TOKENIZED_FORMAT_STRING(message),                             \
63         __VA_ARGS__);                                                        \
64   } while (0)
65 
66 // If the level field is present, clamp it to the maximum value.
67 #if PW_LOG_TOKENIZED_LEVEL_BITS == 0
68 #define _PW_LOG_TOKENIZED_LEVEL(value) ((uintptr_t)0)
69 #else
70 #define _PW_LOG_TOKENIZED_LEVEL(value)                   \
71   (value < ((uintptr_t)1 << PW_LOG_TOKENIZED_LEVEL_BITS) \
72        ? value                                           \
73        : ((uintptr_t)1 << PW_LOG_TOKENIZED_LEVEL_BITS) - 1)
74 #endif  // PW_LOG_TOKENIZED_LEVEL_BITS
75 
76 // If the line number field is present, shift it to its position. Set it to zero
77 // if the line number is too large for PW_LOG_TOKENIZED_LINE_BITS.
78 #if PW_LOG_TOKENIZED_LINE_BITS == 0
79 #define _PW_LOG_TOKENIZED_LINE(line) ((uintptr_t)0)
80 #else
81 #define _PW_LOG_TOKENIZED_LINE(line)                                \
82   ((uintptr_t)(line < (1 << PW_LOG_TOKENIZED_LINE_BITS) ? line : 0) \
83    << PW_LOG_TOKENIZED_LEVEL_BITS)
84 #endif  // PW_LOG_TOKENIZED_LINE_BITS
85 
86 // If the flags field is present, mask it and shift it to its position.
87 #if PW_LOG_TOKENIZED_FLAG_BITS == 0
88 #define _PW_LOG_TOKENIZED_FLAGS(value) ((uintptr_t)0)
89 #else
90 #define _PW_LOG_TOKENIZED_FLAGS(value)                                       \
91   (((uintptr_t)(value) & (((uintptr_t)1 << PW_LOG_TOKENIZED_FLAG_BITS) - 1)) \
92    << (PW_LOG_TOKENIZED_LEVEL_BITS + PW_LOG_TOKENIZED_LINE_BITS))
93 #endif  // PW_LOG_TOKENIZED_FLAG_BITS
94 
95 // If the module field is present, shift it to its position.
96 #if PW_LOG_TOKENIZED_MODULE_BITS == 0
97 #define _PW_LOG_TOKENIZED_MODULE(value) ((uintptr_t)0)
98 #else
99 #define _PW_LOG_TOKENIZED_MODULE(value)                  \
100   ((uintptr_t)(value) << ((PW_LOG_TOKENIZED_LEVEL_BITS + \
101                            PW_LOG_TOKENIZED_LINE_BITS +  \
102                            PW_LOG_TOKENIZED_FLAG_BITS)))
103 #endif  // PW_LOG_TOKENIZED_MODULE_BITS
104