blob: 19f4e88257e1a9e4ac6ab6e4041b79a3cd4f7504 [file] [log] [blame]
// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once
#include <cstdarg>
#include <cstddef>
#include <cstring>
#include <span>
#include "pw_tokenizer/config.h"
#include "pw_tokenizer/internal/argument_types.h"
#include "pw_tokenizer/tokenize.h"
namespace pw {
namespace tokenizer {
// Encodes a tokenized string's arguments to a buffer. The
// pw_tokenizer_ArgTypes parameter specifies the argument types, in place of a
// format string.
//
// Most tokenization implementations may use the EncodedMessage class below.
size_t EncodeArgs(pw_tokenizer_ArgTypes types,
va_list args,
std::span<std::byte> output);
// Encodes a tokenized message to a fixed size buffer. The size of the buffer is
// determined by the PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES config macro.
//
// This class is used to encode tokenized messages passed in from the
// tokenization macros. The macros provided by pw_tokenizer use this class, and
// projects that elect to define their own versions of the tokenization macros
// should use it when possible.
//
// To use the pw::Tokenizer::EncodedMessage, construct it with the token,
// argument types, and va_list from the variadic arguments:
//
// void SendLogMessage(std::span<std::byte> log_data);
//
// extern "C" void TokenizeToSendLogMessage(pw_tokenizer_Token token,
// pw_tokenizer_ArgTypes types,
// ...) {
// va_list args;
// va_start(args, types);
// EncodedMessage encoded_message(token, types, args);
// va_end(args);
//
// SendLogMessage(encoded_message); // EncodedMessage converts to std::span
// }
//
class EncodedMessage {
public:
// Encodes a tokenized message to an internal buffer.
EncodedMessage(pw_tokenizer_Token token,
pw_tokenizer_ArgTypes types,
va_list args) {
std::memcpy(data_, &token, sizeof(token));
args_size_ = EncodeArgs(
types, args, std::span<std::byte>(data_).subspan(sizeof(token)));
}
// The binary-encoded tokenized message.
const std::byte* data() const { return data_; }
// Returns the data() as a pointer to uint8_t instead of std::byte.
const uint8_t* data_as_uint8() const {
return reinterpret_cast<const uint8_t*>(data());
}
// The size of the encoded tokenized message in bytes.
size_t size() const { return sizeof(pw_tokenizer_Token) + args_size_; }
private:
std::byte data_[PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES];
size_t args_size_;
};
static_assert(PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES >=
sizeof(pw_tokenizer_Token),
"PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES must be at least "
"large enough for a token (4 bytes)");
} // namespace tokenizer
} // namespace pw