Skip to content

Commit 270f20a

Browse files
authored
Merge pull request #14305 from NixOS/alignment-utils
libutil: Add alignUp helper function, use in archive.cc
2 parents f05d240 + 22c7386 commit 270f20a

File tree

5 files changed

+45
-1
lines changed

5 files changed

+45
-1
lines changed

src/libutil-tests/alignment.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include "nix/util/alignment.hh"
2+
3+
#include <gtest/gtest.h>
4+
5+
namespace nix {
6+
7+
TEST(alignUp, value)
8+
{
9+
for (uint64_t i = 1; i <= 8; ++i)
10+
EXPECT_EQ(alignUp(i, 8), 8);
11+
}
12+
13+
TEST(alignUp, notAPowerOf2)
14+
{
15+
ASSERT_DEATH({ alignUp(1u, 42); }, "alignment must be a power of 2");
16+
}
17+
18+
} // namespace nix

src/libutil-tests/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ config_priv_h = configure_file(
4444
subdir('nix-meson-build-support/common')
4545

4646
sources = files(
47+
'alignment.cc',
4748
'archive.cc',
4849
'args.cc',
4950
'base-n.cc',

src/libutil/archive.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <strings.h> // for strcasecmp
77

88
#include "nix/util/archive.hh"
9+
#include "nix/util/alignment.hh"
910
#include "nix/util/config-global.hh"
1011
#include "nix/util/posix-source-accessor.hh"
1112
#include "nix/util/source-path.hh"
@@ -133,7 +134,7 @@ static void parseContents(CreateRegularFileSink & sink, Source & source)
133134
sink.preallocateContents(size);
134135

135136
if (sink.skipContents) {
136-
source.skip(size + (size % 8 ? 8 - (size % 8) : 0));
137+
source.skip(alignUp(size, 8));
137138
return;
138139
}
139140

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
///@file
3+
4+
#include <cassert>
5+
#include <type_traits>
6+
#include <cstdint>
7+
#include <bit>
8+
9+
namespace nix {
10+
11+
/// Aligns val upwards to be a multiple of alignment.
12+
///
13+
/// @pre alignment must be a power of 2.
14+
template<typename T>
15+
requires std::is_unsigned_v<T>
16+
constexpr T alignUp(T val, unsigned alignment)
17+
{
18+
assert(std::has_single_bit(alignment) && "alignment must be a power of 2");
19+
T mask = ~(T{alignment} - 1u);
20+
return (val + alignment - 1) & mask;
21+
}
22+
23+
} // namespace nix

src/libutil/include/nix/util/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ include_dirs = [ include_directories('../..') ]
44

55
headers = files(
66
'abstract-setting-to-json.hh',
7+
'alignment.hh',
78
'ansicolor.hh',
89
'archive.hh',
910
'args.hh',

0 commit comments

Comments
 (0)