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