Skip to content

Commit 06cc797

Browse files
committed
Add hex_reader and hex_writer (base16 streamers).
1 parent 52787ef commit 06cc797

14 files changed

Lines changed: 491 additions & 0 deletions

File tree

Makefile.am

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ test_libbitcoin_system_test_SOURCES = \
380380
test/stream/streamers/byte_flipper.cpp \
381381
test/stream/streamers/byte_reader.cpp \
382382
test/stream/streamers/byte_writer.cpp \
383+
test/stream/streamers/hex_reader.cpp \
384+
test/stream/streamers/hex_writer.cpp \
383385
test/stream/streamers/sha256_writer.cpp \
384386
test/stream/streamers/sha256t_writer.cpp \
385387
test/stream/streamers/sha256x2_writer.cpp \
@@ -742,6 +744,8 @@ include_bitcoin_system_impl_stream_streamers_HEADERS = \
742744
include/bitcoin/system/impl/stream/streamers/bit_writer.ipp \
743745
include/bitcoin/system/impl/stream/streamers/byte_reader.ipp \
744746
include/bitcoin/system/impl/stream/streamers/byte_writer.ipp \
747+
include/bitcoin/system/impl/stream/streamers/hex_reader.ipp \
748+
include/bitcoin/system/impl/stream/streamers/hex_writer.ipp \
745749
include/bitcoin/system/impl/stream/streamers/sha256_writer.ipp \
746750
include/bitcoin/system/impl/stream/streamers/sha256t_writer.ipp \
747751
include/bitcoin/system/impl/stream/streamers/sha256x2_writer.ipp
@@ -871,6 +875,8 @@ include_bitcoin_system_stream_streamers_HEADERS = \
871875
include/bitcoin/system/stream/streamers/byte_flipper.hpp \
872876
include/bitcoin/system/stream/streamers/byte_reader.hpp \
873877
include/bitcoin/system/stream/streamers/byte_writer.hpp \
878+
include/bitcoin/system/stream/streamers/hex_reader.hpp \
879+
include/bitcoin/system/stream/streamers/hex_writer.hpp \
874880
include/bitcoin/system/stream/streamers/sha256_writer.hpp \
875881
include/bitcoin/system/stream/streamers/sha256t_writer.hpp \
876882
include/bitcoin/system/stream/streamers/sha256x2_writer.hpp

builds/cmake/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,8 @@ if (with-tests)
859859
"../../test/stream/streamers/byte_flipper.cpp"
860860
"../../test/stream/streamers/byte_reader.cpp"
861861
"../../test/stream/streamers/byte_writer.cpp"
862+
"../../test/stream/streamers/hex_reader.cpp"
863+
"../../test/stream/streamers/hex_writer.cpp"
862864
"../../test/stream/streamers/sha256_writer.cpp"
863865
"../../test/stream/streamers/sha256t_writer.cpp"
864866
"../../test/stream/streamers/sha256x2_writer.cpp"

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@
303303
<ClCompile Include="..\..\..\..\test\stream\streamers\byte_flipper.cpp" />
304304
<ClCompile Include="..\..\..\..\test\stream\streamers\byte_reader.cpp" />
305305
<ClCompile Include="..\..\..\..\test\stream\streamers\byte_writer.cpp" />
306+
<ClCompile Include="..\..\..\..\test\stream\streamers\hex_reader.cpp" />
307+
<ClCompile Include="..\..\..\..\test\stream\streamers\hex_writer.cpp" />
306308
<ClCompile Include="..\..\..\..\test\stream\streamers\sha256_writer.cpp" />
307309
<ClCompile Include="..\..\..\..\test\stream\streamers\sha256t_writer.cpp" />
308310
<ClCompile Include="..\..\..\..\test\stream\streamers\sha256x2_writer.cpp" />

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,12 @@
579579
<ClCompile Include="..\..\..\..\test\stream\streamers\byte_writer.cpp">
580580
<Filter>src\stream\streamers</Filter>
581581
</ClCompile>
582+
<ClCompile Include="..\..\..\..\test\stream\streamers\hex_reader.cpp">
583+
<Filter>src\stream\streamers</Filter>
584+
</ClCompile>
585+
<ClCompile Include="..\..\..\..\test\stream\streamers\hex_writer.cpp">
586+
<Filter>src\stream\streamers</Filter>
587+
</ClCompile>
582588
<ClCompile Include="..\..\..\..\test\stream\streamers\sha256_writer.cpp">
583589
<Filter>src\stream\streamers</Filter>
584590
</ClCompile>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@
501501
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\byte_flipper.hpp" />
502502
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\byte_reader.hpp" />
503503
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\byte_writer.hpp" />
504+
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\hex_reader.hpp" />
505+
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\hex_writer.hpp" />
504506
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\interfaces\bitflipper.hpp" />
505507
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\interfaces\bitreader.hpp" />
506508
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\interfaces\bitwriter.hpp" />
@@ -674,6 +676,8 @@
674676
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\bit_writer.ipp" />
675677
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\byte_reader.ipp" />
676678
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\byte_writer.ipp" />
679+
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\hex_reader.ipp" />
680+
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\hex_writer.ipp" />
677681
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\sha256_writer.ipp" />
678682
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\sha256t_writer.ipp" />
679683
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\sha256x2_writer.ipp" />

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,12 @@
12531253
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\byte_writer.hpp">
12541254
<Filter>include\bitcoin\system\stream\streamers</Filter>
12551255
</ClInclude>
1256+
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\hex_reader.hpp">
1257+
<Filter>include\bitcoin\system\stream\streamers</Filter>
1258+
</ClInclude>
1259+
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\hex_writer.hpp">
1260+
<Filter>include\bitcoin\system\stream\streamers</Filter>
1261+
</ClInclude>
12561262
<ClInclude Include="..\..\..\..\include\bitcoin\system\stream\streamers\interfaces\bitflipper.hpp">
12571263
<Filter>include\bitcoin\system\stream\streamers\interfaces</Filter>
12581264
</ClInclude>
@@ -1768,6 +1774,12 @@
17681774
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\byte_writer.ipp">
17691775
<Filter>include\bitcoin\system\impl\stream\streamers</Filter>
17701776
</None>
1777+
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\hex_reader.ipp">
1778+
<Filter>include\bitcoin\system\impl\stream\streamers</Filter>
1779+
</None>
1780+
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\hex_writer.ipp">
1781+
<Filter>include\bitcoin\system\impl\stream\streamers</Filter>
1782+
</None>
17711783
<None Include="..\..\..\..\include\bitcoin\system\impl\stream\streamers\sha256_writer.ipp">
17721784
<Filter>include\bitcoin\system\impl\stream\streamers</Filter>
17731785
</None>

include/bitcoin/system.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@
221221
#include <bitcoin/system/stream/streamers/byte_flipper.hpp>
222222
#include <bitcoin/system/stream/streamers/byte_reader.hpp>
223223
#include <bitcoin/system/stream/streamers/byte_writer.hpp>
224+
#include <bitcoin/system/stream/streamers/hex_reader.hpp>
225+
#include <bitcoin/system/stream/streamers/hex_writer.hpp>
224226
#include <bitcoin/system/stream/streamers/sha256_writer.hpp>
225227
#include <bitcoin/system/stream/streamers/sha256t_writer.hpp>
226228
#include <bitcoin/system/stream/streamers/sha256x2_writer.hpp>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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_STREAM_STREAMERS_BASE16_READER_IPP
20+
#define LIBBITCOIN_SYSTEM_STREAM_STREAMERS_BASE16_READER_IPP
21+
22+
#include <bitcoin/system/define.hpp>
23+
#include <bitcoin/system/radix/radix.hpp>
24+
#include <bitcoin/system/stream/streamers/byte_reader.hpp>
25+
26+
namespace libbitcoin {
27+
namespace system {
28+
29+
// constructors
30+
// ----------------------------------------------------------------------------
31+
32+
template <typename IStream>
33+
hex_reader<IStream>::hex_reader(IStream& source) NOEXCEPT
34+
: base(source)
35+
{
36+
}
37+
38+
template <typename IStream>
39+
hex_reader<IStream>::hex_reader(IStream& source,
40+
const base::memory_arena& arena) NOEXCEPT
41+
: base(source, arena)
42+
{
43+
}
44+
45+
// protected
46+
// ----------------------------------------------------------------------------
47+
48+
template <typename IStream>
49+
void hex_reader<IStream>::do_read_bytes(uint8_t* buffer,
50+
size_t size) NOEXCEPT
51+
{
52+
if (!is_even(size))
53+
{
54+
this->invalidate();
55+
return;
56+
}
57+
58+
char chars[two];
59+
const auto bytes = pointer_cast<uint8_t>(&chars[zero]);
60+
61+
// Iteration avoids writing to dynamically-allocated buffer of size.
62+
for (auto octet = buffer; octet < std::next(buffer, size); ++octet)
63+
{
64+
base::do_read_bytes(bytes, two);
65+
if (!is_base16(chars[0]) || !is_base16(chars[1]))
66+
{
67+
this->invalidate();
68+
return;
69+
}
70+
71+
*octet = from_base16_characters(chars[0], chars[1]);
72+
}
73+
}
74+
75+
} // namespace system
76+
} // namespace libbitcoin
77+
78+
#endif
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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_STREAM_STREAMERS_BASE16_WRITER_IPP
20+
#define LIBBITCOIN_SYSTEM_STREAM_STREAMERS_BASE16_WRITER_IPP
21+
22+
#include <algorithm>
23+
#include <bitcoin/system/define.hpp>
24+
#include <bitcoin/system/radix/radix.hpp>
25+
#include <bitcoin/system/stream/streamers/byte_writer.hpp>
26+
27+
namespace libbitcoin {
28+
namespace system {
29+
30+
// constructors
31+
// ----------------------------------------------------------------------------
32+
33+
template <typename OStream>
34+
hex_writer<OStream>::hex_writer(OStream& sink) NOEXCEPT
35+
: base(sink)
36+
{
37+
}
38+
39+
// protected
40+
// ----------------------------------------------------------------------------
41+
42+
template <typename OStream>
43+
void hex_writer<OStream>::do_write_bytes(const uint8_t* data,
44+
size_t size) NOEXCEPT
45+
{
46+
char chars[two];
47+
const auto bytes = pointer_cast<uint8_t>(&chars[zero]);
48+
49+
// Iteration avoids writing to dynamically-allocated buffer of size.
50+
std::for_each_n(data, size, [&](uint8_t octet) NOEXCEPT
51+
{
52+
chars[0] = to_base16_hi_character(octet);
53+
chars[1] = to_base16_lo_character(octet);
54+
base::do_write_bytes(bytes, two);
55+
});
56+
}
57+
58+
} // namespace system
59+
} // namespace libbitcoin
60+
61+
#endif

include/bitcoin/system/stream/streamers.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include <bitcoin/system/stream/streamers/byte_flipper.hpp>
3737
#include <bitcoin/system/stream/streamers/byte_reader.hpp>
3838
#include <bitcoin/system/stream/streamers/byte_writer.hpp>
39+
#include <bitcoin/system/stream/streamers/hex_reader.hpp>
40+
#include <bitcoin/system/stream/streamers/hex_writer.hpp>
3941
#include <bitcoin/system/stream/streamers/interfaces/bitflipper.hpp>
4042
#include <bitcoin/system/stream/streamers/interfaces/byteflipper.hpp>
4143
#include <bitcoin/system/stream/streamers/interfaces/bitreader.hpp>
@@ -90,6 +92,18 @@ namespace read
9092
/// A bit reader that copies from a data_reference via std::istream.
9193
using copy = make_streamer<copy_source<data_reference>, bit_reader>;
9294
}
95+
96+
namespace base16
97+
{
98+
/// A byte reader that reads base16 from a std::istream.
99+
using istream = hex_reader<std::istream>;
100+
101+
/// A fast byte reader that reads base16 from a system::istream.
102+
using fast = hex_reader<system::istream<>>;
103+
104+
/// A byte reader that copies base16 from a data_reference via std::istream.
105+
using copy = make_streamer<copy_source<data_reference>, hex_reader>;
106+
}
93107
}
94108

95109
namespace write
@@ -129,6 +143,24 @@ namespace write
129143
using text = push<std::string>;
130144
using data = push<data_chunk>;
131145
}
146+
147+
namespace base16
148+
{
149+
/// A base16 byte writer that writes to a std::ostream.
150+
using ostream = hex_writer<std::ostream>;
151+
152+
/// A fast base16 writer that writes to a system::ostream.
153+
using fast = hex_writer<system::ostream<>>;
154+
155+
/// A base16 byte writer that copies to a data_slab.
156+
using copy = make_streamer<copy_sink<data_slab>, hex_writer>;
157+
158+
/// A base16 byte writer that inserts into a container.
159+
template <typename Container>
160+
using push = make_streamer<push_sink<Container>, hex_writer>;
161+
using text = push<std::string>;
162+
using data = push<data_chunk>;
163+
}
132164
}
133165

134166
namespace flip

0 commit comments

Comments
 (0)