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