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"
49#define PW_TOKENIZER_DEFAULT_DOMAIN ""
67#define PW_TOKENIZE_STRING(...) \
68 PW_DELEGATE_BY_ARG_COUNT(_PW_TOKENIZE_STRING_, __VA_ARGS__)
72#define _PW_TOKENIZE_STRING_1(string_literal) \
73 PW_TOKENIZE_STRING_DOMAIN(PW_TOKENIZER_DEFAULT_DOMAIN, string_literal)
75#define _PW_TOKENIZE_STRING_2(domain, string_literal) \
76 PW_TOKENIZE_STRING_DOMAIN(domain, string_literal)
92#define PW_TOKENIZE_STRING_EXPR(...) \
93 PW_DELEGATE_BY_ARG_COUNT(_PW_TOKENIZE_STRING_EXPR_, __VA_ARGS__)
97#define _PW_TOKENIZE_STRING_EXPR_1(string_literal) \
98 _PW_TOKENIZE_STRING_EXPR_2(PW_TOKENIZER_DEFAULT_DOMAIN, string_literal)
100#define _PW_TOKENIZE_STRING_EXPR_2(domain, string_literal) \
102 constexpr uint32_t lambda_ret_token = \
103 PW_TOKENIZE_STRING_DOMAIN(domain, string_literal); \
104 return lambda_ret_token; \
114#define PW_TOKENIZE_STRING_DOMAIN(domain, string_literal) \
115 PW_TOKENIZE_STRING_MASK(domain, UINT32_MAX, string_literal)
122#define PW_TOKENIZE_STRING_DOMAIN_EXPR(domain, string_literal) \
124 constexpr uint32_t lambda_ret_token = \
125 PW_TOKENIZE_STRING_DOMAIN(domain, string_literal); \
126 return lambda_ret_token; \
135#define PW_TOKENIZE_STRING_MASK(domain, mask, string_literal) \
136 _PW_TOKENIZER_MASK_TOKEN(mask, string_literal); \
138 static_assert(0 < (mask) && (mask) <= UINT32_MAX, \
139 "Tokenizer masks must be non-zero uint32_t values."); \
141 PW_TOKENIZER_DEFINE_TOKEN( \
142 _PW_TOKENIZER_MASK_TOKEN(mask, string_literal), domain, string_literal)
150#define PW_TOKENIZE_STRING_MASK_EXPR(domain, mask, string_literal) \
152 constexpr uint32_t lambda_ret_token = \
153 PW_TOKENIZE_STRING_MASK(domain, mask, string_literal); \
154 return lambda_ret_token; \
159#define _PW_TOKENIZER_MASK_TOKEN(mask, string_literal) \
160 ((pw_tokenizer_Token)(mask) & PW_TOKENIZER_STRING_TOKEN(string_literal))
194#define PW_TOKENIZE_TO_BUFFER(buffer, buffer_size_pointer, format, ...) \
195 PW_TOKENIZE_TO_BUFFER_DOMAIN(PW_TOKENIZER_DEFAULT_DOMAIN, \
197 buffer_size_pointer, \
205#define PW_TOKENIZE_TO_BUFFER_DOMAIN( \
206 domain, buffer, buffer_size_pointer, format, ...) \
207 PW_TOKENIZE_TO_BUFFER_MASK( \
208 domain, UINT32_MAX, buffer, buffer_size_pointer, format, __VA_ARGS__)
213#define PW_TOKENIZE_TO_BUFFER_MASK( \
214 domain, mask, buffer, buffer_size_pointer, format, ...) \
216 PW_TOKENIZE_FORMAT_STRING(domain, mask, format, __VA_ARGS__); \
217 _pw_tokenizer_ToBuffer(buffer, \
218 buffer_size_pointer, \
219 PW_TOKENIZER_REPLACE_FORMAT_STRING(__VA_ARGS__)); \
244#define PW_TOKENIZER_REPLACE_FORMAT_STRING(...) \
245 _PW_TOKENIZER_REPLACE_FORMAT_STRING(PW_EMPTY_ARGS(__VA_ARGS__), __VA_ARGS__)
249#define _PW_TOKENIZER_REPLACE_FORMAT_STRING(empty_args, ...) \
250 _PW_CONCAT_2(_PW_TOKENIZER_REPLACE_FORMAT_STRING_, empty_args)(__VA_ARGS__)
252#define _PW_TOKENIZER_REPLACE_FORMAT_STRING_1() _pw_tokenizer_token, 0u
253#define _PW_TOKENIZER_REPLACE_FORMAT_STRING_0(...) \
254 _pw_tokenizer_token, PW_TOKENIZER_ARG_TYPES(__VA_ARGS__), __VA_ARGS__
267#define PW_TOKENIZER_ARG_TYPES(...) \
268 PW_DELEGATE_BY_ARG_COUNT(_PW_TOKENIZER_TYPES_, __VA_ARGS__)
276void _pw_tokenizer_ToBuffer(
void* buffer,
277 size_t* buffer_size_bytes,
279 pw_tokenizer_ArgTypes types,
283static inline void pw_tokenizer_CheckFormatString(
const char* format, ...)
286static inline
void pw_tokenizer_CheckFormatString(const
char* format, ...) {
309#define PW_TOKENIZE_FORMAT_STRING(domain, mask, format, ...) \
311 PW_FUNCTION_ARG_COUNT(__VA_ARGS__) <= PW_TOKENIZER_MAX_SUPPORTED_ARGS, \
312 "Tokenized strings cannot have more than " \
313 PW_STRINGIFY(PW_TOKENIZER_MAX_SUPPORTED_ARGS) " arguments; " \
314 PW_STRINGIFY(PW_FUNCTION_ARG_COUNT(__VA_ARGS__)) \
315 " arguments were used for " #format " (" #__VA_ARGS__ ")"); \
316 PW_TOKENIZE_FORMAT_STRING_ANY_ARG_COUNT(domain, mask, format, __VA_ARGS__)
333#define PW_TOKENIZE_FORMAT_STRING_ANY_ARG_COUNT(domain, mask, format, ...) \
335 pw_tokenizer_CheckFormatString(format PW_COMMA_ARGS(__VA_ARGS__)); \
338 _PW_TOKENIZE_VALIDATE_FORMAT_STRING(format); \
341 static _PW_TOKENIZER_CONST pw_tokenizer_Token _pw_tokenizer_token = \
342 _PW_TOKENIZER_MASK_TOKEN(mask, format); \
344 PW_TOKENIZER_DEFINE_TOKEN(_pw_tokenizer_token, domain, format)
349#define _PW_TOKENIZER_UNIQUE(prefix) PW_CONCAT(prefix, __LINE__, _, __COUNTER__)
353#define _PW_TOKENIZER_CONST constexpr
363#define PW_TOKENIZER_DEFINE_TOKEN(token, domain, string) \
364 static_assert(::pw::tokenizer::internal::ValidDomain(domain), \
365 "pw_tokenizer domains may only contain alphanumeric " \
366 "characters, underscore, or colon, and cannot start with a " \
367 "number; space characters are ignored"); \
368 alignas(1) static constexpr auto _PW_TOKENIZER_SECTION _PW_TOKENIZER_UNIQUE( \
369 _pw_tokenizer_string_entry_) = \
370 ::pw::tokenizer::internal::MakeEntry(token, domain, string)
376#define _PW_TOKENIZE_VALIDATE_FORMAT_STRING(format) \
378 static_assert(!::pw::tokenizer::internal::Contains(format, "%.*s"), \
379 "The %.*s specifier is not supported." \
380 " See https://pwbug.dev/408040194"); \
383namespace pw::tokenizer {
390constexpr bool Contains(
const char* haystack,
const char* needle) {
391 std::string_view haystack_view(haystack);
392 return haystack_view.find(needle) != std::string_view::npos;
400#define _PW_TOKENIZER_CONST const
401#define _PW_ALIGNAS(alignment) __attribute__((aligned(alignment)))
403#define PW_TOKENIZER_DEFINE_TOKEN(token, domain, string) \
404 _PW_ALIGNAS(1) static const _PW_TOKENIZER_STRING_ENTRY(token, domain, string)
407#define _PW_TOKENIZE_VALIDATE_FORMAT_STRING(format) \
454#define _PW_TOKENIZER_SECTION \
455 PW_KEEP_IN_SECTION(PW_STRINGIFY(_PW_TOKENIZER_UNIQUE(.pw.)))
457#define _PW_TOKENIZER_SECTION \
458 PW_KEEP_IN_SECTION(PW_STRINGIFY(_PW_TOKENIZER_UNIQUE(.pw_tokenizer.entries.)))
#define PW_PRINTF_FORMAT(format_index, parameter_index)
Definition: compiler.h:89
uint32_t pw_tokenizer_Token
Definition: tokenize.h:41
#define PW_TOKENIZER_DEFAULT_DOMAIN
Definition: tokenize.h:49