Botan 3.9.0
Crypto and TLS for C&
data_src.cpp
Go to the documentation of this file.
1/*
2* DataSource
3* (C) 1999-2007 Jack Lloyd
4* 2005 Matthew Gregan
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/data_src.h>
10
11#include <botan/exceptn.h>
12#include <botan/mem_ops.h>
13#include <botan/internal/fmt.h>
14#include <botan/internal/mem_utils.h>
15#include <algorithm>
16#include <istream>
17
18#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
19 #include <fstream>
20#endif
21
22namespace Botan {
23
24/*
25* Read a single byte from the DataSource
26*/
27size_t DataSource::read_byte(uint8_t& out) {
28 return read(&out, 1);
29}
30
31/*
32* Read a single byte from the DataSource
33*/
34std::optional<uint8_t> DataSource::read_byte() {
35 uint8_t b = 0;
36 if(this->read(&b, 1) == 1) {
37 return b;
38 } else {
39 return {};
40 }
41}
42
43/*
44* Peek a single byte from the DataSource
45*/
46size_t DataSource::peek_byte(uint8_t& out) const {
47 return peek(&out, 1, 0);
48}
49
50/*
51* Discard the next N bytes of the data
52*/
53size_t DataSource::discard_next(size_t n) {
54 uint8_t buf[64] = {0};
55 size_t discarded = 0;
56
57 while(n > 0) {
58 const size_t got = this->read(buf, std::min(n, sizeof(buf)));
59 discarded += got;
60 n -= got;
61
62 if(got == 0) {
63 break;
64 }
65 }
66
67 return discarded;
68}
69
70/*
71* Read from a memory buffer
72*/
73size_t DataSource_Memory::read(uint8_t out[], size_t length) {
74 const size_t got = std::min<size_t>(m_source.size() - m_offset, length);
75 copy_mem(out, m_source.data() + m_offset, got);
76 m_offset += got;
77 return got;
78}
79
81 return (n <= (m_source.size() - m_offset));
82}
83
84/*
85* Peek into a memory buffer
86*/
87size_t DataSource_Memory::peek(uint8_t out[], size_t length, size_t peek_offset) const {
88 const size_t bytes_left = m_source.size() - m_offset;
89 if(peek_offset >= bytes_left) {
90 return 0;
91 }
92
93 const size_t got = std::min(bytes_left - peek_offset, length);
94 copy_mem(out, &m_source[m_offset + peek_offset], got);
95 return got;
96}
97
98/*
99* Check if the memory buffer is empty
100*/
102 return (m_offset == m_source.size());
103}
104
105/*
106* DataSource_Memory Constructor
107*/
109
110/*
111* Read from a stream
112*/
113size_t DataSource_Stream::read(uint8_t out[], size_t length) {
114 m_source.read(cast_uint8_ptr_to_char(out), length);
115 if(m_source.bad()) {
116 throw Stream_IO_Error("DataSource_Stream::read: Source failure");
117 }
118
119 const size_t got = static_cast<size_t>(m_source.gcount());
120 m_total_read += got;
121 return got;
122}
123
125 const std::streampos orig_pos = m_source.tellg();
126 m_source.seekg(0, std::ios::end);
127 const size_t avail = static_cast<size_t>(m_source.tellg() - orig_pos);
128 m_source.seekg(orig_pos);
129 return (avail >= n);
130}
131
132/*
133* Peek into a stream
134*/
135size_t DataSource_Stream::peek(uint8_t out[], size_t length, size_t offset) const {
136 if(end_of_data()) {
137 throw Invalid_State("DataSource_Stream: Cannot peek when out of data");
138 }
139
140 size_t got = 0;
141
142 if(offset > 0) {
143 secure_vector<uint8_t> buf(offset);
144 m_source.read(cast_uint8_ptr_to_char(buf.data()), buf.size());
145 if(m_source.bad()) {
146 throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
147 }
148 got = static_cast<size_t>(m_source.gcount());
149 }
150
151 if(got == offset) {
152 m_source.read(cast_uint8_ptr_to_char(out), length);
153 if(m_source.bad()) {
154 throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
155 }
156 got = static_cast<size_t>(m_source.gcount());
157 }
158
159 if(m_source.eof()) {
160 m_source.clear();
161 }
162 m_source.seekg(m_total_read, std::ios::beg);
163
164 return got;
165}
166
167/*
168* Check if the stream is empty or in error
169*/
171 return (!m_source.good());
172}
173
174/*
175* Return a human-readable ID for this stream
176*/
177std::string DataSource_Stream::id() const {
178 return m_identifier;
179}
180
181#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
182
183/*
184* DataSource_Stream Constructor
185*/
186DataSource_Stream::DataSource_Stream(std::string_view path, bool use_binary) :
187 m_identifier(path),
188 m_source_memory(std::make_unique<std::ifstream>(std::string(path), use_binary ? std::ios::binary : std::ios::in)),
189 m_source(*m_source_memory),
190 m_total_read(0) {
191 if(!m_source.good()) {
192 throw Stream_IO_Error(fmt("DataSource: Failure opening file '{}'", path));
193 }
194}
195
196#endif
197
198/*
199* DataSource_Stream Constructor
200*/
201DataSource_Stream::DataSource_Stream(std::istream& in, std::string_view name) :
202 m_identifier(name), m_source(in), m_total_read(0) {}
203
205
206} // namespace Botan
DataSource_Memory(std::string_view in)
Definition data_src.cpp:108
size_t read(uint8_t buf[], size_t length) override
Definition data_src.cpp:73
bool check_available(size_t n) override
Definition data_src.cpp:80
size_t peek(uint8_t buf[], size_t length, size_t offset) const override
Definition data_src.cpp:87
bool end_of_data() const override
Definition data_src.cpp:101
bool end_of_data() const override
Definition data_src.cpp:170
BOTAN_FUTURE_EXPLICIT DataSource_Stream(std::istream &in, std::string_view id="<std::istream>")
Definition data_src.cpp:201
size_t read(uint8_t buf[], size_t length) override
Definition data_src.cpp:113
size_t peek(uint8_t buf[], size_t length, size_t offset) const override
Definition data_src.cpp:135
bool check_available(size_t n) override
Definition data_src.cpp:124
std::string id() const override
Definition data_src.cpp:177
size_t peek_byte(uint8_t &out) const
Definition data_src.cpp:46
std::optional< uint8_t > read_byte()
Definition data_src.cpp:34
size_t discard_next(size_t N)
Definition data_src.cpp:53
virtual size_t peek(uint8_t out[], size_t length, size_t peek_offset) const =0
virtual size_t read(uint8_t out[], size_t length)=0
std::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
Definition mem_utils.h:28
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:145
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition mem_ops.h:282
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69