• 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 #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