Browse Source

refactor: upgrade project structure

master
Dnomd343 8 months ago
parent
commit
7feecc71cb
  1. 2
      .gitignore
  2. 6
      .gitmodules
  3. 26
      CMakeLists.txt
  4. 26
      benchmark.cc
  5. 29
      md5_core.h
  6. 40
      src/md5.h
  7. 9
      src/md5_core.cc
  8. 0
      src/md5_math.h
  9. 17
      test/md5_update.cc
  10. 10
      third_party/ThirdParty.cmake
  11. 1
      third_party/benchmark
  12. 1
      third_party/googletest

2
.gitignore

@ -0,0 +1,2 @@
/.idea/
/cmake-build*/

6
.gitmodules

@ -0,0 +1,6 @@
[submodule "third_party/googletest"]
path = third_party/googletest
url = https://github.com/google/googletest.git
[submodule "third_party/benchmark"]
path = third_party/benchmark
url = https://github.com/google/benchmark.git

26
CMakeLists.txt

@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.5)
project(md5sum LANGUAGES CXX)
option(MD5_ENABLE_TESTING "Enable testing of the md5sum library." ON)
option(MD5_ENABLE_BENCHMARK "Enable benchmark of the md5sum library." ON)
set(CMAKE_CXX_STANDARD 20)
add_compile_options(-fno-rtti -fno-exceptions -Wall -Wextra)
add_library(md5sum STATIC src/md5_core.cc)
target_include_directories(md5sum INTERFACE src/)
include(third_party/ThirdParty.cmake)
add_library(md5sum::md5sum ALIAS md5sum)
if (MD5_ENABLE_TESTING)
enable_testing()
add_executable(md5_test test/md5_update.cc)
target_link_libraries(md5_test PRIVATE md5sum::md5sum GTest::gtest_main)
endif()
if (MD5_ENABLE_BENCHMARK)
add_executable(md5_benchmark benchmark.cc)
target_link_libraries(md5_benchmark PRIVATE md5sum::md5sum benchmark::benchmark_main)
endif()

26
benchmark.cc

@ -0,0 +1,26 @@
#include <benchmark/benchmark.h>
#include "md5.h"
std::string test_data() {
char data[64];
for (char i = 0; i < 64; ++i) {
data[i] = i;
}
return {data, data + 64};
}
static void BM_MD5_NEXT(benchmark::State &state) {
const auto data = test_data();
md5::MD5::md5_ctx c;
md5::MD5::md5_reset(&c);
for (auto _ : state) {
md5::MD5::md5_update(&c, data.c_str(), 64);
}
}
BENCHMARK(BM_MD5_NEXT);
BENCHMARK_MAIN();

29
md5_core.h

@ -1,29 +0,0 @@
#pragma once
#include <cstdint>
namespace md5 {
constexpr uint32_t MD5_A = 0x67452301;
constexpr uint32_t MD5_B = 0xefcdab89;
constexpr uint32_t MD5_C = 0x98badcfe;
constexpr uint32_t MD5_D = 0x10325476;
struct md5_ctx {
uint32_t A = MD5_A;
uint32_t B = MD5_B;
uint32_t C = MD5_C;
uint32_t D = MD5_D;
uint64_t size = 0;
};
/// Reset md5 ctx with algorithm constants.
void md5_reset(md5_ctx *ctx);
/// Update md5 ctx with specified data, note that `len` is a multiple of 64.
void md5_update(md5_ctx *ctx, const void *buffer, uint64_t len);
/// Update and end the md5 hash with the specified data, the value of `len` has no limit.
void md5_final(md5_ctx *ctx, const void *buffer, uint64_t len);
} // namespace md5

40
src/md5.h

@ -0,0 +1,40 @@
#pragma once
#include <cstdint>
namespace md5 {
class MD5 {
public:
MD5() = default;
public:
static constexpr uint32_t MD5_A = 0x67452301;
static constexpr uint32_t MD5_B = 0xefcdab89;
static constexpr uint32_t MD5_C = 0x98badcfe;
static constexpr uint32_t MD5_D = 0x10325476;
struct md5_ctx {
uint32_t A = MD5_A;
uint32_t B = MD5_B;
uint32_t C = MD5_C;
uint32_t D = MD5_D;
uint64_t size = 0;
};
/// Reset md5 ctx with algorithm constants.
static void md5_reset(md5_ctx *ctx);
/// Update md5 ctx with specified data, note that `len` is a multiple of 64.
static void md5_update(md5_ctx *ctx, const void *buffer, uint64_t len);
/// Update and end the md5 hash with the specified data, the value of `len` has no limit.
static void md5_final(md5_ctx *ctx, const void *buffer, uint64_t len);
private:
md5_ctx ctx_;
char buffer_[64] = {};
char buffer_size_ = 0;
};
} // namespace md5

9
md5_core.cc → src/md5_core.cc

@ -1,5 +1,6 @@
#include <cstring> #include <cstring>
#include "md5_core.h"
#include "md5.h"
#include "md5_math.h" #include "md5_math.h"
#define RA A, B, C, D #define RA A, B, C, D
@ -58,7 +59,7 @@ consteval uint32_t T(int index) { // index -> [0, 64)
return static_cast<uint32_t>(std::abs(val) * 0x100000000); return static_cast<uint32_t>(std::abs(val) * 0x100000000);
} }
void md5_reset(md5_ctx *ctx) { void MD5::md5_reset(md5_ctx *ctx) {
ctx->A = MD5_A; ctx->A = MD5_A;
ctx->B = MD5_B; ctx->B = MD5_B;
ctx->C = MD5_C; ctx->C = MD5_C;
@ -66,7 +67,7 @@ void md5_reset(md5_ctx *ctx) {
ctx->size = 0; ctx->size = 0;
} }
void md5_update(md5_ctx *ctx, const void *data, uint64_t len) { void MD5::md5_update(md5_ctx *ctx, const void *data, uint64_t len) {
auto *block = reinterpret_cast<const uint32_t *>(data); auto *block = reinterpret_cast<const uint32_t *>(data);
auto *limit = block + (len >> 2); auto *limit = block + (len >> 2);
auto A = ctx->A; auto A = ctx->A;
@ -97,7 +98,7 @@ void md5_update(md5_ctx *ctx, const void *data, uint64_t len) {
ctx->size += len; // processed size in byte ctx->size += len; // processed size in byte
} }
void md5_final(md5_ctx *ctx, const void *data, uint64_t len) { void MD5::md5_final(md5_ctx *ctx, const void *data, uint64_t len) {
if (len >= 120) { // len -> [64 + 56, INF) if (len >= 120) { // len -> [64 + 56, INF)
auto size = len & ~(uint64_t)0b111111; auto size = len & ~(uint64_t)0b111111;
md5_update(ctx, data, size); md5_update(ctx, data, size);

0
md5_math.h → src/md5_math.h

17
main.cc → test/md5_update.cc

@ -1,6 +1,6 @@
#include <iostream> #include <gtest/gtest.h>
#include "md5_core.h" #include "md5.h"
std::string test_data() { std::string test_data() {
char data[64]; char data[64];
@ -10,7 +10,7 @@ std::string test_data() {
return {data, data + 64}; return {data, data + 64};
} }
void dump_ctx(const md5::md5_ctx *c) { void dump_ctx(const md5::MD5::md5_ctx *c) {
std::cout << std::hex << c->A << std::endl; std::cout << std::hex << c->A << std::endl;
std::cout << std::hex << c->B << std::endl; std::cout << std::hex << c->B << std::endl;
std::cout << std::hex << c->C << std::endl; std::cout << std::hex << c->C << std::endl;
@ -18,10 +18,10 @@ void dump_ctx(const md5::md5_ctx *c) {
std::cout << std::dec << c->size << std::endl; std::cout << std::dec << c->size << std::endl;
} }
int main() { TEST(md5sum, main) {
auto data = test_data() + test_data() + test_data() + test_data(); auto data = test_data() + test_data() + test_data() + test_data();
md5::md5_ctx c; md5::MD5::md5_ctx c;
dump_ctx(&c); dump_ctx(&c);
// md5::md5_update(&c, data.c_str(), data.size()); // md5::md5_update(&c, data.c_str(), data.size());
@ -33,10 +33,11 @@ int main() {
// md5::md5_update(&c, data.c_str(), data.size()); // md5::md5_update(&c, data.c_str(), data.size());
// dump_ctx(&c); // dump_ctx(&c);
md5::md5_final(&c, data.c_str(), 0); md5::MD5::md5_final(&c, data.c_str(), 0);
dump_ctx(&c); dump_ctx(&c);
md5::md5_reset(&c); md5::MD5::md5_reset(&c);
md5::md5_final(&c, data.c_str(), data.size()); md5::MD5::md5_final(&c, data.c_str(), data.size());
dump_ctx(&c); dump_ctx(&c);
} }

10
third_party/ThirdParty.cmake

@ -0,0 +1,10 @@
if (MD5_ENABLE_TESTING)
add_subdirectory(third_party/googletest/ EXCLUDE_FROM_ALL)
endif()
if (MD5_ENABLE_BENCHMARK)
set(BENCHMARK_ENABLE_LTO ON)
set(BENCHMARK_ENABLE_TESTING OFF)
set(BENCHMARK_ENABLE_EXCEPTIONS OFF)
add_subdirectory(third_party/benchmark/ EXCLUDE_FROM_ALL)
endif()

1
third_party/benchmark

@ -0,0 +1 @@
Subproject commit 344117638c8ff7e239044fd0fa7085839fc03021

1
third_party/googletest

@ -0,0 +1 @@
Subproject commit f8d7d77c06936315286eb55f8de22cd23c188571
Loading…
Cancel
Save