Skip to content

Commit 1e1d6e4

Browse files
committed
Add config::version (4 segment uint32_t).
1 parent ddc9e0c commit 1e1d6e4

File tree

11 files changed

+570
-2
lines changed

11 files changed

+570
-2
lines changed

Makefile.am

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ src_libbitcoin_system_la_SOURCES = \
8282
src/config/transaction.cpp \
8383
src/config/url.cpp \
8484
src/config/utilities.cpp \
85+
src/config/version.cpp \
8586
src/crypto/aes256.cpp \
8687
src/crypto/der_parser.cpp \
8788
src/crypto/ec_context.cpp \
@@ -261,6 +262,7 @@ test_libbitcoin_system_test_SOURCES = \
261262
test/config/printer.cpp \
262263
test/config/url.cpp \
263264
test/config/utilities.cpp \
265+
test/config/version.cpp \
264266
test/crypto/aes256.cpp \
265267
test/crypto/elliptic_curve.cpp \
266268
test/crypto/pseudo_random.cpp \
@@ -533,7 +535,8 @@ include_bitcoin_system_config_HEADERS = \
533535
include/bitcoin/system/config/script.hpp \
534536
include/bitcoin/system/config/transaction.hpp \
535537
include/bitcoin/system/config/url.hpp \
536-
include/bitcoin/system/config/utilities.hpp
538+
include/bitcoin/system/config/utilities.hpp \
539+
include/bitcoin/system/config/version.hpp
537540

538541
include_bitcoin_system_cryptodir = ${includedir}/bitcoin/system/crypto
539542
include_bitcoin_system_crypto_HEADERS = \

builds/cmake/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ add_library( ${CANONICAL_LIB_NAME}
515515
"../../src/config/transaction.cpp"
516516
"../../src/config/url.cpp"
517517
"../../src/config/utilities.cpp"
518+
"../../src/config/version.cpp"
518519
"../../src/crypto/aes256.cpp"
519520
"../../src/crypto/der_parser.cpp"
520521
"../../src/crypto/ec_context.cpp"
@@ -740,6 +741,7 @@ if (with-tests)
740741
"../../test/config/printer.cpp"
741742
"../../test/config/url.cpp"
742743
"../../test/config/utilities.cpp"
744+
"../../test/config/version.cpp"
743745
"../../test/crypto/aes256.cpp"
744746
"../../test/crypto/elliptic_curve.cpp"
745747
"../../test/crypto/pseudo_random.cpp"

builds/msvc/vs2022/libbitcoin-system-test/libbitcoin-system-test.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
<ClCompile Include="..\..\..\..\test\config\printer.cpp" />
162162
<ClCompile Include="..\..\..\..\test\config\url.cpp" />
163163
<ClCompile Include="..\..\..\..\test\config\utilities.cpp" />
164+
<ClCompile Include="..\..\..\..\test\config\version.cpp" />
164165
<ClCompile Include="..\..\..\..\test\constants.cpp" />
165166
<ClCompile Include="..\..\..\..\test\constraints.cpp" />
166167
<ClCompile Include="..\..\..\..\test\crypto\aes256.cpp" />

builds/msvc/vs2022/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@
219219
<ClCompile Include="..\..\..\..\test\config\utilities.cpp">
220220
<Filter>src\config</Filter>
221221
</ClCompile>
222+
<ClCompile Include="..\..\..\..\test\config\version.cpp">
223+
<Filter>src\config</Filter>
224+
</ClCompile>
222225
<ClCompile Include="..\..\..\..\test\constants.cpp">
223226
<Filter>src</Filter>
224227
</ClCompile>

builds/msvc/vs2022/libbitcoin-system/libbitcoin-system.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
</ClCompile>
196196
<ClCompile Include="..\..\..\..\src\config\url.cpp" />
197197
<ClCompile Include="..\..\..\..\src\config\utilities.cpp" />
198+
<ClCompile Include="..\..\..\..\src\config\version.cpp" />
198199
<ClCompile Include="..\..\..\..\src\crypto\aes256.cpp" />
199200
<ClCompile Include="..\..\..\..\src\crypto\der_parser.cpp" />
200201
<ClCompile Include="..\..\..\..\src\crypto\ec_context.cpp" />
@@ -357,6 +358,7 @@
357358
<ClInclude Include="..\..\..\..\include\bitcoin\system\config\transaction.hpp" />
358359
<ClInclude Include="..\..\..\..\include\bitcoin\system\config\url.hpp" />
359360
<ClInclude Include="..\..\..\..\include\bitcoin\system\config\utilities.hpp" />
361+
<ClInclude Include="..\..\..\..\include\bitcoin\system\config\version.hpp" />
360362
<ClInclude Include="..\..\..\..\include\bitcoin\system\constants.hpp" />
361363
<ClInclude Include="..\..\..\..\include\bitcoin\system\constraints.hpp" />
362364
<ClInclude Include="..\..\..\..\include\bitcoin\system\crypto\aes256.hpp" />

builds/msvc/vs2022/libbitcoin-system/libbitcoin-system.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@
381381
<ClCompile Include="..\..\..\..\src\config\utilities.cpp">
382382
<Filter>src\config</Filter>
383383
</ClCompile>
384+
<ClCompile Include="..\..\..\..\src\config\version.cpp">
385+
<Filter>src\config</Filter>
386+
</ClCompile>
384387
<ClCompile Include="..\..\..\..\src\crypto\aes256.cpp">
385388
<Filter>src\crypto</Filter>
386389
</ClCompile>
@@ -821,6 +824,9 @@
821824
<ClInclude Include="..\..\..\..\include\bitcoin\system\config\utilities.hpp">
822825
<Filter>include\bitcoin\system\config</Filter>
823826
</ClInclude>
827+
<ClInclude Include="..\..\..\..\include\bitcoin\system\config\version.hpp">
828+
<Filter>include\bitcoin\system\config</Filter>
829+
</ClInclude>
824830
<ClInclude Include="..\..\..\..\include\bitcoin\system\constants.hpp">
825831
<Filter>include\bitcoin\system</Filter>
826832
</ClInclude>

include/bitcoin/system/config/config.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,6 @@
4141
#include <bitcoin/system/config/transaction.hpp>
4242
#include <bitcoin/system/config/url.hpp>
4343
#include <bitcoin/system/config/utilities.hpp>
44+
#include <bitcoin/system/config/version.hpp>
4445

4546
#endif
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/**
2+
* Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS)
3+
*
4+
* This file is part of libbitcoin.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
#ifndef LIBBITCOIN_SYSTEM_CONFIG_VERSION_HPP
20+
#define LIBBITCOIN_SYSTEM_CONFIG_VERSION_HPP
21+
22+
#include <memory>
23+
#include <bitcoin/system/define.hpp>
24+
25+
namespace libbitcoin {
26+
namespace system {
27+
namespace config {
28+
29+
/// Container for a protocol version tuple with up to four segments.
30+
/// Segments are non-negative integers, padded with zeros for fewer than four.
31+
/// The format is major.minor[.subminor[.patch]] with at least one dot.
32+
class BC_API version
33+
{
34+
public:
35+
typedef std::shared_ptr<version> ptr;
36+
37+
DEFAULT_COPY_MOVE_DESTRUCT(version);
38+
39+
version() NOEXCEPT;
40+
41+
/// Deserialize from dotted string (throws on invalid format).
42+
version(const std::string& version_str) THROWS;
43+
44+
/// Construct from individual segments (2 to 4, pads with zeros).
45+
version(uint32_t major, uint32_t minor, uint32_t subminor={},
46+
uint32_t patch={}) NOEXCEPT;
47+
48+
/// Properties.
49+
/// -----------------------------------------------------------------------
50+
51+
/// Access to the internal segments array.
52+
const std::array<uint32_t, 4>& segments() const NOEXCEPT;
53+
54+
/// Methods.
55+
/// -----------------------------------------------------------------------
56+
57+
/// The version is 0.0.0.0.
58+
bool is_default() const NOEXCEPT;
59+
60+
/// Serialize to dot string, omitting trailing zero segments (minimum 2).
61+
std::string to_string() const NOEXCEPT;
62+
63+
/// Operators.
64+
/// -----------------------------------------------------------------------
65+
66+
/// Deserialize from input stream (throws on invalid format).
67+
friend std::istream& operator>>(std::istream& input, version& argument) THROWS;
68+
69+
/// Serialize to output stream.
70+
friend std::ostream& operator<<(std::ostream& output,
71+
const version& argument) NOEXCEPT;
72+
73+
private:
74+
// This is not thread safe.
75+
std::array<uint32_t, 4> segments_;
76+
};
77+
78+
/// Lexicographical comparison.
79+
BC_API bool operator==(const version& left, const version& right) NOEXCEPT;
80+
BC_API bool operator!=(const version& left, const version& right) NOEXCEPT;
81+
BC_API bool operator<(const version& left, const version& right) NOEXCEPT;
82+
BC_API bool operator<=(const version& left, const version& right) NOEXCEPT;
83+
BC_API bool operator>(const version& left, const version& right) NOEXCEPT;
84+
BC_API bool operator>=(const version& left, const version& right) NOEXCEPT;
85+
86+
typedef std::vector<version> versions;
87+
88+
} // namespace config
89+
} // namespace system
90+
} // namespace libbitcoin
91+
92+
namespace std
93+
{
94+
template<>
95+
struct hash<bc::system::config::version>
96+
{
97+
size_t operator()(const bc::system::config::version& value) const NOEXCEPT
98+
{
99+
return std::hash<std::string>{}(value.to_string());
100+
}
101+
};
102+
} // namespace std
103+
104+
#endif

include/bitcoin/system/impl/serial/deserialize.ipp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <algorithm>
2323
#include <iterator>
2424
#include <sstream>
25+
#include <utility>
2526
#include <bitcoin/system/data/data.hpp>
2627
#include <bitcoin/system/define.hpp>
2728
#include <bitcoin/system/math/math.hpp>
@@ -107,7 +108,14 @@ bool deserialize(Value& out, const std::string_view& text) NOEXCEPT
107108
// This can convert garbage to zero, use is_ascii_number for pre-assurance.
108109
try
109110
{
110-
std::istringstream istream(trim_copy(text));
111+
auto trimmed = trim_copy(text);
112+
if constexpr (is_integer<Value> && !is_signed<Value>)
113+
{
114+
if (!trimmed.empty() && trimmed.front() == '-')
115+
return false;
116+
}
117+
118+
std::istringstream istream(std::move(trimmed));
111119
istream >> out;
112120
return !istream.fail();
113121
}

src/config/version.cpp

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/**
2+
* Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS)
3+
*
4+
* This file is part of libbitcoin.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
#include <bitcoin/system/config/version.hpp>
20+
21+
#include <algorithm>
22+
#include <sstream>
23+
#include <bitcoin/system/data/data.hpp>
24+
#include <bitcoin/system/define.hpp>
25+
#include <bitcoin/system/math/math.hpp>
26+
#include <bitcoin/system/serial/serial.hpp>
27+
28+
namespace libbitcoin {
29+
namespace system {
30+
namespace config {
31+
32+
// Contructors.
33+
// ----------------------------------------------------------------------------
34+
35+
// Default version is 0.0.0.0 and serializes as "0.0".
36+
version::version() NOEXCEPT
37+
: version(0, 0, 0, 0)
38+
{
39+
}
40+
41+
version::version(const std::string& version) THROWS
42+
: version()
43+
{
44+
std::istringstream(version) >> (*this);
45+
}
46+
47+
version::version(uint32_t major, uint32_t minor, uint32_t subminor,
48+
uint32_t patch) NOEXCEPT
49+
: segments_{ major, minor, subminor, patch }
50+
{
51+
}
52+
53+
// Properties.
54+
// ----------------------------------------------------------------------------
55+
56+
const std::array<uint32_t, 4>& version::segments() const NOEXCEPT
57+
{
58+
return segments_;
59+
}
60+
61+
// Methods.
62+
// ----------------------------------------------------------------------------
63+
64+
bool version::is_default() const NOEXCEPT
65+
{
66+
constexpr std::array<uint32_t, 4> default_{};
67+
return segments_ == default_;
68+
}
69+
70+
std::string version::to_string() const NOEXCEPT
71+
{
72+
std::ostringstream value{};
73+
value << (*this);
74+
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
75+
return value.str();
76+
BC_POP_WARNING()
77+
}
78+
79+
// Operators.
80+
// ----------------------------------------------------------------------------
81+
82+
bool operator==(const version& left, const version& right) NOEXCEPT
83+
{
84+
return left.segments() == right.segments();
85+
}
86+
87+
bool operator!=(const version& left, const version& right) NOEXCEPT
88+
{
89+
return !(left == right);
90+
}
91+
92+
bool operator<(const version& left, const version& right) NOEXCEPT
93+
{
94+
return std::lexicographical_compare(
95+
left.segments().begin(), left.segments().end(),
96+
right.segments().begin(), right.segments().end());
97+
}
98+
99+
bool operator<=(const version& left, const version& right) NOEXCEPT
100+
{
101+
return left < right || left == right;
102+
}
103+
104+
bool operator>(const version& left, const version& right) NOEXCEPT
105+
{
106+
return right < left;
107+
}
108+
109+
bool operator>=(const version& left, const version& right) NOEXCEPT
110+
{
111+
return right <= left;
112+
}
113+
114+
std::istream& operator>>(std::istream& input,
115+
version& argument) THROWS
116+
{
117+
std::string value;
118+
input >> value;
119+
120+
using namespace system;
121+
const auto tokens = system::split(value, ".");
122+
const auto count = tokens.size();
123+
if (count < 2u || count > 4u)
124+
throw istream_exception(value);
125+
126+
argument = {};
127+
for (size_t index{}; index < count; ++index)
128+
if (!deserialize(argument.segments_.at(index), tokens.at(index)))
129+
throw istream_exception(value);
130+
131+
return input;
132+
}
133+
134+
std::ostream& operator<<(std::ostream& output,
135+
const version& argument) NOEXCEPT
136+
{
137+
size_t last{ 3 };
138+
while (last > 1u && is_zero(argument.segments_.at(last)))
139+
--last;
140+
141+
for (size_t index{}; index <= last; ++index)
142+
{
143+
BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
144+
if (!is_zero(index)) output << '.';
145+
output << argument.segments_.at(index);
146+
BC_POP_WARNING()
147+
}
148+
149+
return output;
150+
}
151+
152+
} // namespace config
153+
} // namespace system
154+
} // namespace libbitcoin

0 commit comments

Comments
 (0)