• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Selects the hash macro implementation to use. The implementation selected
16 // depends on the language (C or C++) and value of
17 // PW_TOKENIZER_CFG_C_HASH_LENGTH. The options are:
18 //
19 //   - C++ hash constexpr function, which works for any hash length
20 //   - C 80-character hash macro
21 //   - C 96-character hash macro
22 //   - C 128-character hash macro
23 //
24 // C hash macros for other lengths may be generated using generate_hash_macro.py
25 // and added to this file.
26 #pragma once
27 
28 #include <stdint.h>
29 
30 #define _PW_TOKENIZER_ENTRY_MAGIC UINT32_C(0xBAA98DEE)
31 
32 #ifdef __cplusplus
33 
34 #include <array>
35 
36 namespace pw {
37 namespace tokenizer {
38 namespace internal {
39 
40 // The C++ tokenzied string entry supports both string literals and char arrays,
41 // such as __func__.
42 template <uint32_t kDomainSize, uint32_t kStringSize>
PW_PACKED(class)43 PW_PACKED(class)
44 Entry {
45  public:
46   constexpr Entry(uint32_t token,
47                   const char(&domain)[kDomainSize],
48                   const char(&string)[kStringSize])
49       : magic_(_PW_TOKENIZER_ENTRY_MAGIC),
50         token_(token),
51         domain_size_(kDomainSize),
52         string_size_(kStringSize),
53         domain_(std::to_array(domain)),
54         string_(std::to_array(string)) {}
55 
56  private:
57   static_assert(kStringSize > 0u && kDomainSize > 0u);
58 
59   uint32_t magic_;
60   uint32_t token_;
61   uint32_t domain_size_;
62   uint32_t string_size_;
63   std::array<char, kDomainSize> domain_;
64   std::array<char, kStringSize> string_;
65 };
66 
67 }  // namespace internal
68 }  // namespace tokenizer
69 }  // namespace pw
70 
71 #else  // In C, define a struct inline with appropriately-sized string members.
72 
73 #define _PW_TOKENIZER_STRING_ENTRY(                   \
74     calculated_token, domain_literal, string_literal) \
75   PW_PACKED(struct) {                                 \
76     uint32_t magic;                                   \
77     uint32_t token;                                   \
78     uint32_t domain_size;                             \
79     uint32_t string_length;                           \
80     char domain[sizeof(domain_literal)];              \
81     char string[sizeof(string_literal)];              \
82   }                                                   \
83   _PW_TOKENIZER_UNIQUE(_pw_tokenizer_string_entry_)   \
84   _PW_TOKENIZER_SECTION = {                           \
85       _PW_TOKENIZER_ENTRY_MAGIC,                      \
86       calculated_token,                               \
87       sizeof(domain_literal),                         \
88       sizeof(string_literal),                         \
89       domain_literal,                                 \
90       string_literal,                                 \
91   }
92 
93 #endif  // __cplusplus
94 
95 // In C++17, use a constexpr function to calculate the hash.
96 #if defined(__cpp_constexpr) && __cpp_constexpr >= 201304L && \
97     defined(__cpp_inline_variables)
98 
99 #include "pw_tokenizer/hash.h"
100 
101 #define PW_TOKENIZER_STRING_TOKEN(format) ::pw::tokenizer::Hash(format)
102 
103 #else  // In C or older C++ code, use the hashing macro.
104 
105 #if PW_TOKENIZER_CFG_C_HASH_LENGTH == 80
106 
107 #include "pw_tokenizer/internal/pw_tokenizer_65599_fixed_length_80_hash_macro.h"
108 #define PW_TOKENIZER_STRING_TOKEN PW_TOKENIZER_65599_FIXED_LENGTH_80_HASH
109 
110 #elif PW_TOKENIZER_CFG_C_HASH_LENGTH == 96
111 
112 #include "pw_tokenizer/internal/pw_tokenizer_65599_fixed_length_96_hash_macro.h"
113 #define PW_TOKENIZER_STRING_TOKEN PW_TOKENIZER_65599_FIXED_LENGTH_96_HASH
114 
115 #elif PW_TOKENIZER_CFG_C_HASH_LENGTH == 128
116 
117 #include "pw_tokenizer/internal/pw_tokenizer_65599_fixed_length_128_hash_macro.h"
118 #define PW_TOKENIZER_STRING_TOKEN PW_TOKENIZER_65599_FIXED_LENGTH_128_HASH
119 
120 #elif PW_TOKENIZER_CFG_C_HASH_LENGTH == 256
121 
122 #include "pw_tokenizer/internal/pw_tokenizer_65599_fixed_length_256_hash_macro.h"
123 #define PW_TOKENIZER_STRING_TOKEN PW_TOKENIZER_65599_FIXED_LENGTH_256_HASH
124 
125 #else  // unsupported hash length
126 
127 // Only hash lengths for which there is a corresponding macro header
128 // (pw_tokenizer/internal/mash_macro_#.h) are supported. Additional macros may
129 // be generated with the generate_hash_macro.py function. New macro headers must
130 // be added to this file.
131 #error "Unsupported value for PW_TOKENIZER_CFG_C_HASH_LENGTH"
132 
133 // Define a dummy macro to give clearer compilation errors.
134 #define PW_TOKENIZER_STRING_TOKEN(unused) 0u
135 
136 #endif  // PW_TOKENIZER_CFG_C_HASH_LENGTH
137 
138 #endif  // __cpp_constexpr >= 201304L && defined(__cpp_inline_variables)
139