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