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 #pragma once 15 16 #include <cstdarg> 17 #include <cstddef> 18 #include <cstring> 19 #include <span> 20 21 #include "pw_tokenizer/config.h" 22 #include "pw_tokenizer/internal/argument_types.h" 23 #include "pw_tokenizer/tokenize.h" 24 25 namespace pw { 26 namespace tokenizer { 27 28 // Encodes a tokenized string's arguments to a buffer. The 29 // pw_tokenizer_ArgTypes parameter specifies the argument types, in place of a 30 // format string. 31 // 32 // Most tokenization implementations may use the EncodedMessage class below. 33 size_t EncodeArgs(pw_tokenizer_ArgTypes types, 34 va_list args, 35 std::span<std::byte> output); 36 37 // Encodes a tokenized message to a fixed size buffer. The size of the buffer is 38 // determined by the PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES config macro. 39 // 40 // This class is used to encode tokenized messages passed in from the 41 // tokenization macros. The macros provided by pw_tokenizer use this class, and 42 // projects that elect to define their own versions of the tokenization macros 43 // should use it when possible. 44 // 45 // To use the pw::Tokenizer::EncodedMessage, construct it with the token, 46 // argument types, and va_list from the variadic arguments: 47 // 48 // void SendLogMessage(std::span<std::byte> log_data); 49 // 50 // extern "C" void TokenizeToSendLogMessage(pw_tokenizer_Token token, 51 // pw_tokenizer_ArgTypes types, 52 // ...) { 53 // va_list args; 54 // va_start(args, types); 55 // EncodedMessage encoded_message(token, types, args); 56 // va_end(args); 57 // 58 // SendLogMessage(encoded_message); // EncodedMessage converts to std::span 59 // } 60 // 61 class EncodedMessage { 62 public: 63 // Encodes a tokenized message to an internal buffer. EncodedMessage(pw_tokenizer_Token token,pw_tokenizer_ArgTypes types,va_list args)64 EncodedMessage(pw_tokenizer_Token token, 65 pw_tokenizer_ArgTypes types, 66 va_list args) { 67 std::memcpy(data_, &token, sizeof(token)); 68 args_size_ = EncodeArgs( 69 types, args, std::span<std::byte>(data_).subspan(sizeof(token))); 70 } 71 72 // The binary-encoded tokenized message. data()73 const std::byte* data() const { return data_; } 74 75 // Returns the data() as a pointer to uint8_t instead of std::byte. data_as_uint8()76 const uint8_t* data_as_uint8() const { 77 return reinterpret_cast<const uint8_t*>(data()); 78 } 79 80 // The size of the encoded tokenized message in bytes. size()81 size_t size() const { return sizeof(pw_tokenizer_Token) + args_size_; } 82 83 private: 84 std::byte data_[PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES]; 85 size_t args_size_; 86 }; 87 88 static_assert(PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES >= 89 sizeof(pw_tokenizer_Token), 90 "PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES must be at least " 91 "large enough for a token (4 bytes)"); 92 93 } // namespace tokenizer 94 } // namespace pw 95