29#include "pw_polyfill/static_assert.h"
30#include "pw_preprocessor/arguments.h"
31#include "pw_preprocessor/compiler.h"
32#include "pw_preprocessor/concat.h"
33#include "pw_preprocessor/util.h"
34#include "pw_tokenizer/internal/argument_types.h"
35#include "pw_tokenizer/internal/tokenize_string.h"
39typedef uint32_t pw_tokenizer_Token;
47#define PW_TOKENIZER_DEFAULT_DOMAIN ""
65#define PW_TOKENIZE_STRING(...) \
66 PW_DELEGATE_BY_ARG_COUNT(_PW_TOKENIZE_STRING_, __VA_ARGS__)
68#define _PW_TOKENIZE_STRING_1(string_literal) \
69 PW_TOKENIZE_STRING_DOMAIN(PW_TOKENIZER_DEFAULT_DOMAIN, string_literal)
71#define _PW_TOKENIZE_STRING_2(domain, string_literal) \
72 PW_TOKENIZE_STRING_DOMAIN(domain, string_literal)
86#define PW_TOKENIZE_STRING_EXPR(...) \
87 PW_DELEGATE_BY_ARG_COUNT(_PW_TOKENIZE_STRING_EXPR_, __VA_ARGS__)
89#define _PW_TOKENIZE_STRING_EXPR_1(string_literal) \
90 _PW_TOKENIZE_STRING_EXPR_2(PW_TOKENIZER_DEFAULT_DOMAIN, string_literal)
92#define _PW_TOKENIZE_STRING_EXPR_2(domain, string_literal) \
94 constexpr uint32_t lambda_ret_token = \
95 PW_TOKENIZE_STRING_DOMAIN(domain, string_literal); \
96 return lambda_ret_token; \
101#define PW_TOKENIZE_STRING_DOMAIN(domain, string_literal) \
102 PW_TOKENIZE_STRING_MASK(domain, UINT32_MAX, string_literal)
106#define PW_TOKENIZE_STRING_DOMAIN_EXPR(domain, string_literal) \
108 constexpr uint32_t lambda_ret_token = \
109 PW_TOKENIZE_STRING_DOMAIN(domain, string_literal); \
110 return lambda_ret_token; \
116#define PW_TOKENIZE_STRING_MASK(domain, mask, string_literal) \
117 _PW_TOKENIZER_MASK_TOKEN(mask, string_literal); \
119 static_assert(0 < (mask) && (mask) <= UINT32_MAX, \
120 "Tokenizer masks must be non-zero uint32_t values."); \
122 PW_TOKENIZER_DEFINE_TOKEN( \
123 _PW_TOKENIZER_MASK_TOKEN(mask, string_literal), domain, string_literal)
128#define PW_TOKENIZE_STRING_MASK_EXPR(domain, mask, string_literal) \
130 constexpr uint32_t lambda_ret_token = \
131 PW_TOKENIZE_STRING_MASK(domain, mask, string_literal); \
132 return lambda_ret_token; \
135#define _PW_TOKENIZER_MASK_TOKEN(mask, string_literal) \
136 ((pw_tokenizer_Token)(mask) & PW_TOKENIZER_STRING_TOKEN(string_literal))
168#define PW_TOKENIZE_TO_BUFFER(buffer, buffer_size_pointer, format, ...) \
169 PW_TOKENIZE_TO_BUFFER_DOMAIN(PW_TOKENIZER_DEFAULT_DOMAIN, \
171 buffer_size_pointer, \
177#define PW_TOKENIZE_TO_BUFFER_DOMAIN( \
178 domain, buffer, buffer_size_pointer, format, ...) \
179 PW_TOKENIZE_TO_BUFFER_MASK( \
180 domain, UINT32_MAX, buffer, buffer_size_pointer, format, __VA_ARGS__)
184#define PW_TOKENIZE_TO_BUFFER_MASK( \
185 domain, mask, buffer, buffer_size_pointer, format, ...) \
187 PW_TOKENIZE_FORMAT_STRING(domain, mask, format, __VA_ARGS__); \
188 _pw_tokenizer_ToBuffer(buffer, \
189 buffer_size_pointer, \
190 PW_TOKENIZER_REPLACE_FORMAT_STRING(__VA_ARGS__)); \
215#define PW_TOKENIZER_REPLACE_FORMAT_STRING(...) \
216 _PW_TOKENIZER_REPLACE_FORMAT_STRING(PW_EMPTY_ARGS(__VA_ARGS__), __VA_ARGS__)
218#define _PW_TOKENIZER_REPLACE_FORMAT_STRING(empty_args, ...) \
219 _PW_CONCAT_2(_PW_TOKENIZER_REPLACE_FORMAT_STRING_, empty_args)(__VA_ARGS__)
221#define _PW_TOKENIZER_REPLACE_FORMAT_STRING_1() _pw_tokenizer_token, 0u
222#define _PW_TOKENIZER_REPLACE_FORMAT_STRING_0(...) \
223 _pw_tokenizer_token, PW_TOKENIZER_ARG_TYPES(__VA_ARGS__), __VA_ARGS__
234#define PW_TOKENIZER_ARG_TYPES(...) \
235 PW_DELEGATE_BY_ARG_COUNT(_PW_TOKENIZER_TYPES_, __VA_ARGS__)
241void _pw_tokenizer_ToBuffer(
void* buffer,
242 size_t* buffer_size_bytes,
243 pw_tokenizer_Token token,
244 pw_tokenizer_ArgTypes types,
248static inline void pw_tokenizer_CheckFormatString(
const char* format, ...)
251static inline
void pw_tokenizer_CheckFormatString(const
char* format, ...) {
270#define PW_TOKENIZE_FORMAT_STRING(domain, mask, format, ...) \
272 PW_FUNCTION_ARG_COUNT(__VA_ARGS__) <= PW_TOKENIZER_MAX_SUPPORTED_ARGS, \
273 "Tokenized strings cannot have more than " \
274 PW_STRINGIFY(PW_TOKENIZER_MAX_SUPPORTED_ARGS) " arguments; " \
275 PW_STRINGIFY(PW_FUNCTION_ARG_COUNT(__VA_ARGS__)) \
276 " arguments were used for " #format " (" #__VA_ARGS__ ")"); \
277 PW_TOKENIZE_FORMAT_STRING_ANY_ARG_COUNT(domain, mask, format, __VA_ARGS__)
295#define PW_TOKENIZE_FORMAT_STRING_ANY_ARG_COUNT(domain, mask, format, ...) \
297 pw_tokenizer_CheckFormatString(format PW_COMMA_ARGS(__VA_ARGS__)); \
300 _PW_TOKENIZE_VALIDATE_FORMAT_STRING(format); \
303 static _PW_TOKENIZER_CONST pw_tokenizer_Token _pw_tokenizer_token = \
304 _PW_TOKENIZER_MASK_TOKEN(mask, format); \
306 PW_TOKENIZER_DEFINE_TOKEN(_pw_tokenizer_token, domain, format)
309#define _PW_TOKENIZER_UNIQUE(prefix) PW_CONCAT(prefix, __LINE__, _, __COUNTER__)
313#define _PW_TOKENIZER_CONST constexpr
321#define PW_TOKENIZER_DEFINE_TOKEN(token, domain, string) \
322 static_assert(::pw::tokenizer::internal::ValidDomain(domain), \
323 "pw_tokenizer domains may only contain alphanumeric " \
324 "characters, underscore, or colon, and cannot start with a " \
325 "number; space characters are ignored"); \
326 alignas(1) static constexpr auto _PW_TOKENIZER_SECTION _PW_TOKENIZER_UNIQUE( \
327 _pw_tokenizer_string_entry_) = \
328 ::pw::tokenizer::internal::MakeEntry(token, domain, string)
332#define _PW_TOKENIZE_VALIDATE_FORMAT_STRING(format) \
334 static_assert(!::pw::tokenizer::internal::Contains(format, "%.*s"), \
335 "The %.*s specifier is not supported." \
336 " See https://pwbug.dev/408040194"); \
339namespace pw::tokenizer {
341using Token = ::pw_tokenizer_Token;
342inline constexpr const char* kDefaultDomain = PW_TOKENIZER_DEFAULT_DOMAIN;
346constexpr bool Contains(
const char* haystack,
const char* needle) {
347 std::string_view haystack_view(haystack);
348 return haystack_view.find(needle) != std::string_view::npos;
356#define _PW_TOKENIZER_CONST const
357#define _PW_ALIGNAS(alignment) __attribute__((aligned(alignment)))
359#define PW_TOKENIZER_DEFINE_TOKEN(token, domain, string) \
360 _PW_ALIGNAS(1) static const _PW_TOKENIZER_STRING_ENTRY(token, domain, string)
363#define _PW_TOKENIZE_VALIDATE_FORMAT_STRING(format) \
410#define _PW_TOKENIZER_SECTION \
411 PW_KEEP_IN_SECTION(PW_STRINGIFY(_PW_TOKENIZER_UNIQUE(.pw.)))
413#define _PW_TOKENIZER_SECTION \
414 PW_KEEP_IN_SECTION(PW_STRINGIFY(_PW_TOKENIZER_UNIQUE(.pw_tokenizer.entries.)))
#define PW_PRINTF_FORMAT(format_index, parameter_index)
Definition: compiler.h:86