blob: 9baa37ec75a2f548efdc755c89f0dc76d35830a1 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_FORENSICS_FEEDBACK_DATA_SYSTEM_LOG_RECORDER_ENCODING_LZ4_UTILS_H_
#define SRC_DEVELOPER_FORENSICS_FEEDBACK_DATA_SYSTEM_LOG_RECORDER_ENCODING_LZ4_UTILS_H_
#include <cstdint>
#include <string>
#include <lz4/lz4.h>
#include "src/developer/forensics/feedback_data/constants.h"
namespace forensics {
namespace feedback_data {
namespace system_log_recorder {
constexpr size_t kMaxChunkSize = ::forensics::feedback_data::kMaxWriteSize.ToBytes();
static_assert(LZ4_COMPRESSBOUND(kMaxChunkSize) > 0, "The chunk size is invalid!");
// The maximum number of bytes that can safely be encoded by the LZ4 encoder. This was computed
// using the LZ4_COMPRESSBOUND formula.
constexpr size_t kMaxEncodeSize = 16305;
static_assert(LZ4_COMPRESSBOUND(kMaxEncodeSize) == kMaxChunkSize,
"The chunk size isn't the same as the compress bound of the max encode size");
// Due to EncodeSize() limitations, enforce that the encode size fits in 2 bytes.
static_assert(LZ4_COMPRESSBOUND(kMaxChunkSize) < UINT16_MAX,
"The encoded chunk size could not fit in 2 bytes!");
static_assert(kMaxChunkSize < 64 * 1024,
"Lz4 utilizes the last 64KB for its algorithm; there is little to no gain for making "
"a chunk > 64KB.");
constexpr size_t kDecoderRingBufferSize = LZ4_DECODER_RING_BUFFER_SIZE(kMaxChunkSize);
// This indicates to the decoder that the encoder reset so it should reset as well.
constexpr size_t kEncodeSizeError = 0;
// The encoder needs additional kMaxChunkSize space because we replace the contents before calling
// the LZ4 encoder.
constexpr size_t kEncoderRingBufferSize = kDecoderRingBufferSize + kMaxChunkSize;
// Encodes the size of the encoded chunk as a fixed-length string that is easily decodable. This
// must be kept in sync with DecodeSize().
//
// The inline keyword avoids breaking the one definition rule.
inline std::string EncodeSize(uint16_t size) {
std::string num(2, '\0');
num[0] = (size >> 8);
num[1] = (size & 0x00FF);
return num;
}
// Reads the uint16_t value from the first two consecutive characters starting at the *data_ptr
// position and updates the *data_ptr position in order to read subsequent data.
//
// The inline keyword avoids breaking the one definition rule.
//
// Note: we do not cast directly into uint16_t to avoid alignment issues.
inline uint16_t DecodeSize(const char** data_ptr) {
uint16_t size = (uint16_t)((unsigned char)(*data_ptr)[0] << 8) + (unsigned char)(*data_ptr)[1];
*data_ptr += 2;
return size;
}
} // namespace system_log_recorder
} // namespace feedback_data
} // namespace forensics
#endif // SRC_DEVELOPER_FORENSICS_FEEDBACK_DATA_SYSTEM_LOG_RECORDER_ENCODING_LZ4_UTILS_H_