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