Bitcoin Core 28.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
streams.cpp
Go to the documentation of this file.
1// Copyright (c) 2009-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or https://opensource.org/license/mit/.
4
5#include <span.h>
6#include <streams.h>
7#include <util/fs_helpers.h>
8
9#include <array>
10
11AutoFile::AutoFile(std::FILE* file, std::vector<std::byte> data_xor)
12 : m_file{file}, m_xor{std::move(data_xor)}
13{
14 if (!IsNull()) {
15 auto pos{std::ftell(m_file)};
16 if (pos >= 0) m_position = pos;
17 }
18}
19
21{
22 if (!m_file) throw std::ios_base::failure("AutoFile::read: file handle is nullptr");
23 size_t ret = std::fread(dst.data(), 1, dst.size(), m_file);
24 if (!m_xor.empty()) {
25 if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::read: position unknown");
27 }
28 if (m_position.has_value()) *m_position += ret;
29 return ret;
30}
31
32void AutoFile::seek(int64_t offset, int origin)
33{
34 if (IsNull()) {
35 throw std::ios_base::failure("AutoFile::seek: file handle is nullptr");
36 }
37 if (std::fseek(m_file, offset, origin) != 0) {
38 throw std::ios_base::failure(feof() ? "AutoFile::seek: end of file" : "AutoFile::seek: fseek failed");
39 }
40 if (origin == SEEK_SET) {
41 m_position = offset;
42 } else if (origin == SEEK_CUR && m_position.has_value()) {
43 *m_position += offset;
44 } else {
45 int64_t r{std::ftell(m_file)};
46 if (r < 0) {
47 throw std::ios_base::failure("AutoFile::seek: ftell failed");
48 }
49 m_position = r;
50 }
51}
52
54{
55 if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::tell: position unknown");
56 return *m_position;
57}
58
60{
61 if (detail_fread(dst) != dst.size()) {
62 throw std::ios_base::failure(feof() ? "AutoFile::read: end of file" : "AutoFile::read: fread failed");
63 }
64}
65
66void AutoFile::ignore(size_t nSize)
67{
68 if (!m_file) throw std::ios_base::failure("AutoFile::ignore: file handle is nullptr");
69 unsigned char data[4096];
70 while (nSize > 0) {
71 size_t nNow = std::min<size_t>(nSize, sizeof(data));
72 if (std::fread(data, 1, nNow, m_file) != nNow) {
73 throw std::ios_base::failure(feof() ? "AutoFile::ignore: end of file" : "AutoFile::ignore: fread failed");
74 }
75 nSize -= nNow;
76 if (m_position.has_value()) *m_position += nNow;
77 }
78}
79
81{
82 if (!m_file) throw std::ios_base::failure("AutoFile::write: file handle is nullptr");
83 if (m_xor.empty()) {
84 if (std::fwrite(src.data(), 1, src.size(), m_file) != src.size()) {
85 throw std::ios_base::failure("AutoFile::write: write failed");
86 }
87 if (m_position.has_value()) *m_position += src.size();
88 } else {
89 if (!m_position.has_value()) throw std::ios_base::failure("AutoFile::write: position unknown");
90 std::array<std::byte, 4096> buf;
91 while (src.size() > 0) {
92 auto buf_now{Span{buf}.first(std::min<size_t>(src.size(), buf.size()))};
93 std::copy(src.begin(), src.begin() + buf_now.size(), buf_now.begin());
94 util::Xor(buf_now, m_xor, *m_position);
95 if (std::fwrite(buf_now.data(), 1, buf_now.size(), m_file) != buf_now.size()) {
96 throw std::ios_base::failure{"XorFile::write: failed"};
97 }
98 src = src.subspan(buf_now.size());
99 *m_position += buf_now.size();
100 }
101 }
102}
103
105{
106 return ::FileCommit(m_file);
107}
108
110{
111 return ferror(m_file);
112}
113
114bool AutoFile::Truncate(unsigned size)
115{
116 return ::TruncateFile(m_file, size);
117}
int ret
bool feof() const
Definition streams.h:404
void ignore(size_t nSize)
Definition streams.cpp:66
bool IsError()
Definition streams.cpp:109
std::vector< std::byte > m_xor
Definition streams.h:392
std::FILE * m_file
Definition streams.h:391
void seek(int64_t offset, int origin)
Definition streams.cpp:32
void read(Span< std::byte > dst)
Definition streams.cpp:59
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
Definition streams.h:425
bool Truncate(unsigned size)
Definition streams.cpp:114
std::size_t detail_fread(Span< std::byte > dst)
Implementation detail, only used internally.
Definition streams.cpp:20
std::optional< int64_t > m_position
Definition streams.h:393
AutoFile(std::FILE *file, std::vector< std::byte > data_xor={})
Definition streams.cpp:11
int64_t tell()
Definition streams.cpp:53
void write(Span< const std::byte > src)
Definition streams.cpp:80
bool Commit()
Definition streams.cpp:104
A Span is an object that can refer to a contiguous sequence of objects.
Definition span.h:98
constexpr std::size_t size() const noexcept
Definition span.h:187
CONSTEXPR_IF_NOT_DEBUG Span< C > subspan(std::size_t offset) const noexcept
Definition span.h:195
CONSTEXPR_IF_NOT_DEBUG Span< C > first(std::size_t count) const noexcept
Definition span.h:205
constexpr C * data() const noexcept
Definition span.h:174
constexpr C * begin() const noexcept
Definition span.h:175
void Xor(Span< std::byte > write, Span< const std::byte > key, size_t key_offset=0)
Definition streams.h:28