1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2026 Fernando Sahmkow
/// @file key_utils.h
/// @brief Inline helpers for CASC key manipulation (EKey/CKey).
///
/// Internal header — not part of the public include path.
#pragma once
#include <whiteout/common_types.h>
#include <array>
#include <cstring>
#include <span>
namespace whiteout::storages::casc {
/// Truncated EKey size used in index lookups.
static constexpr size_t kEKeyTruncSize = 9;
/// 16-byte zero sentinel — used to detect EKey-only TVFS entries.
static constexpr std::array<u8, 16> kZeroKey{};
/// Create a 9-byte truncated EKey span suitable for index lookups.
inline std::span<const u8> eKeyTrunc(const std::array<u8, 16>& key) {
return std::span<const u8>(key.data(), kEKeyTruncSize);
}
/// Create a 9-byte truncated EKey span from a fixed-size span.
inline std::span<const u8> eKeyTrunc(std::span<const u8, 16> key) {
return std::span<const u8>(key.data(), kEKeyTruncSize);
}
/// Fold a 16-byte key into a u64 hash for hash-map lookups.
/// Uses the first 9 bytes (72 bits) instead of 8 to reduce collision probability.
/// Must use exactly 9 bytes because TVFS roots truncate keys to 9 bytes (zero-
/// padded to 16), and lookups must produce the same hash for both truncated and
/// full keys. The 9th byte is folded into the top byte of the u64.
inline u64 keyHash64(const u8* key) {
u64 h = 0;
std::memcpy(&h, key, 8);
h ^= static_cast<u64>(key[8]) << 56;
return h;
}
/// Fold a 16-byte key into a u64 hash for hash-map lookups.
inline u64 keyHash64(const std::array<u8, 16>& key) {
return keyHash64(key.data());
}
/// Check whether a 16-byte key is all zeros (sentinel value).
inline bool isZeroKey(const std::array<u8, 16>& key) {
return key == kZeroKey;
}
/// Hash functor for keying unordered containers on a 16-byte key.
struct KeyHash64 {
size_t operator()(const std::array<u8, 16>& key) const noexcept {
return static_cast<size_t>(keyHash64(key));
}
};
} // namespace whiteout::storages::casc