blob: 021bd22e5ab414fb878143c851a12412cb037d39 [file] [log] [blame]
// Copyright 2022 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.
#include <cstring>
#include "pw_bloat/bloat_this_binary.h"
#include "pw_log/log.h"
#include "pw_preprocessor/compiler.h"
#include "pw_span/span.h"
#ifdef USE_CRC16_CHECKSUM
#include "pw_checksum/crc16_ccitt.h"
using TheChecksum = pw::checksum::Crc16Ccitt;
#endif
#ifdef USE_CRC32_8BIT_CHECKSUM
#include "pw_checksum/crc32.h"
using TheChecksum = pw::checksum::Crc32EightBit;
#endif
#ifdef USE_CRC32_4BIT_CHECKSUM
#include "pw_checksum/crc32.h"
using TheChecksum = pw::checksum::Crc32FourBit;
#endif
#ifdef USE_CRC32_1BIT_CHECKSUM
#include "pw_checksum/crc32.h"
using TheChecksum = pw::checksum::Crc32OneBit;
#endif
namespace pw::checksum {
#ifdef USE_NOOP_CHECKSUM
class NoOpChecksum {
public:
static uint32_t Calculate(span<const std::byte>) { return arbitrary_value; }
// Don't inline to prevent the compiler from optimizing out the checksum.
PW_NO_INLINE void Update(span<const std::byte>) {}
PW_NO_INLINE void Update(std::byte) {}
PW_NO_INLINE uint32_t value() const { return arbitrary_value; }
void clear() {}
private:
// static volatile uint32_t arbitrary_value;
const static uint32_t arbitrary_value = 10;
};
using TheChecksum = NoOpChecksum;
#endif
// Fletcher16 is a simple checksum that shouldn't be used in production, but is
// interesting from a size comparison perspective.
#ifdef USE_FLETCHER16_CHECKSUM
class Fletcher16 {
public:
Fletcher16() : sum1_(0), sum2_(0) {}
// Don't inline to prevent the compiler from optimizing out the checksum.
PW_NO_INLINE static uint32_t Calculate(span<const std::byte> data) {
Fletcher16 checksum;
checksum.Update(data);
return checksum.value();
}
PW_NO_INLINE void Update(span<const std::byte> data) {
for (std::byte b : data) {
sum1_ = (sum1_ + static_cast<uint16_t>(b)) % 255;
sum2_ = (sum2_ + sum1_) % 255;
}
}
PW_NO_INLINE void Update(std::byte) {}
PW_NO_INLINE uint32_t value() const { return (sum2_ << 8) | sum1_; };
void clear() {}
private:
uint16_t sum1_ = 0;
uint16_t sum2_ = 0;
};
using TheChecksum = Fletcher16;
#endif
char buffer[128];
char* volatile get_buffer = buffer;
volatile unsigned get_size;
unsigned RunChecksum() {
// Trick the optimizer and also satisfy the type checker.
get_size = sizeof(buffer);
char* local_buffer = get_buffer;
unsigned local_size = get_size;
// Calculate the checksum and stash it in a volatile variable so the compiler
// can't optimize it out.
TheChecksum checksum;
checksum.Update(pw::as_bytes(span(local_buffer, local_size)));
uint32_t value = static_cast<uint32_t>(checksum.value());
*get_buffer = static_cast<char>(value);
return 0;
}
} // namespace pw::checksum
int main() {
pw::bloat::BloatThisBinary();
return pw::checksum::RunChecksum();
}