GCC Code Coverage Report


ernie/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
51 / 55
92.7%
Branches:
40 / 76
52.6%
Functions:
6 / 6
100.0%

util/disk_cache.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 /// @file disk_cache.cpp
3 /// @brief Cache folder lookup and cache key hashing.
4 #include "ernie/util/disk_cache.h"
5
6 #include <cstdio>
7 #include <cstdlib>
8 #include <fstream>
9 #include <random>
10 #include <system_error>
11
12 namespace ernie {
13
14 4 std::optional<std::filesystem::path> CacheDirectory(const char* variable, std::string_view folder) {
15 4 namespace fs = std::filesystem;
16
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (const char* own = std::getenv(variable)) {
17
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 const std::string_view value(own);
18
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 if (value.empty() || value == "0") {
19 1 return std::nullopt;
20 }
21 3 return fs::path(value);
22 }
23
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 if (const char* xdg = std::getenv("XDG_CACHE_HOME"); xdg != nullptr && *xdg != '\0') {
24
0/8
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ return fs::path(xdg) / "ernie" / folder;
25 }
26 #if defined(_WIN32)
27 if (const char* local = std::getenv("LOCALAPPDATA"); local != nullptr && *local != '\0') {
28 return fs::path(local) / "ernie" / folder;
29 }
30 #else
31
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 if (const char* home = std::getenv("HOME"); home != nullptr && *home != '\0') {
32
6/12
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
18 return fs::path(home) / ".cache" / "ernie" / folder;
33 }
34 #endif
35 ✗ return std::nullopt;
36 }
37
38 42 void CacheKey::Add(std::string_view text) {
39 42 const std::uint64_t size = text.size();
40 42 Bytes(&size, sizeof(size));
41 42 Bytes(text.data(), text.size());
42 42 }
43
44 23 std::string CacheKey::Hex() const {
45 23 char text[33];
46 23 std::snprintf(text, sizeof(text), "%016llx%016llx", static_cast<unsigned long long>(hashes_[0]),
47 23 static_cast<unsigned long long>(hashes_[1]));
48 23 return text;
49 }
50
51 84 void CacheKey::Bytes(const void* data, std::size_t size) {
52 84 const auto* bytes = static_cast<const unsigned char*>(data);
53
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 84 times.
252 for (std::uint64_t& hash : hashes_) {
54
2/2
✓ Branch 0 taken 1276 times.
✓ Branch 1 taken 168 times.
1444 for (std::size_t i = 0; i < size; ++i) {
55 1276 hash = (hash ^ bytes[i]) * 0x100000001b3ull;
56 }
57 }
58 84 }
59
60 4 std::optional<std::vector<float>> ReadCachedFloats(const std::filesystem::path& path,
61 std::size_t count) {
62 4 std::ifstream in(path, std::ios::binary);
63
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 std::vector<float> values(count);
64 4 const auto bytes = static_cast<std::streamsize>(count * sizeof(float));
65
5/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 1 time.
6 if (in.read(reinterpret_cast<char*>(values.data()), bytes) &&
66
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 in.peek() == std::ifstream::traits_type::eof()) {
67 1 return values;
68 }
69 3 return std::nullopt;
70 4 }
71
72 1 void WriteCachedFloats(const std::filesystem::path& path, std::span<const float> values) {
73 1 namespace fs = std::filesystem;
74 1 fs::path partial = path;
75
3/6
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
3 partial += ".part" + std::to_string(std::random_device{}());
76
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 std::error_code error;
77
2/4
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
1 fs::create_directories(path.parent_path(), error);
78 1 {
79
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 std::ofstream out(partial, std::ios::binary);
80
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 out.write(reinterpret_cast<const char*>(values.data()),
81
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 static_cast<std::streamsize>(values.size_bytes()));
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (!out) {
83 ✗ error = std::make_error_code(std::errc::io_error);
84 }
85 1 }
86
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if (!error) {
87 1 fs::rename(partial, path, error);
88 }
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (error) {
90 ✗ fs::remove(partial, error);
91 }
92 1 }
93
94 } // namespace ernie
95