Botan  1.11.34
Crypto and TLS for C++11
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 
13 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
14  #include <fstream>
15 #endif
16 
17 namespace Botan {
18 
19 /*
20 * Read a single byte from the DataSource
21 */
23  {
24  return read(&out, 1);
25  }
26 
27 /*
28 * Peek a single byte from the DataSource
29 */
30 size_t DataSource::peek_byte(byte& out) const
31  {
32  return peek(&out, 1, 0);
33  }
34 
35 /*
36 * Discard the next N bytes of the data
37 */
38 size_t DataSource::discard_next(size_t n)
39  {
40  byte buf[64] = { 0 };
41  size_t discarded = 0;
42 
43  while(n)
44  {
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  return discarded;
54  }
55 
56 /*
57 * Read from a memory buffer
58 */
59 size_t DataSource_Memory::read(byte out[], size_t length)
60  {
61  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  {
69  return (n <= (m_source.size() - m_offset));
70  }
71 
72 /*
73 * Peek into a memory buffer
74 */
75 size_t DataSource_Memory::peek(byte out[], size_t length,
76  size_t peek_offset) const
77  {
78  const size_t bytes_left = m_source.size() - m_offset;
79  if(peek_offset >= bytes_left) return 0;
80 
81  size_t got = std::min(bytes_left - peek_offset, length);
82  copy_mem(out, &m_source[m_offset + peek_offset], got);
83  return got;
84  }
85 
86 /*
87 * Check if the memory buffer is empty
88 */
90  {
91  return (m_offset == m_source.size());
92  }
93 
94 /*
95 * DataSource_Memory Constructor
96 */
97 DataSource_Memory::DataSource_Memory(const std::string& in) :
98  m_source(reinterpret_cast<const byte*>(in.data()),
99  reinterpret_cast<const byte*>(in.data()) + in.length()),
100  m_offset(0)
101  {
102  }
103 
104 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
105 
106 /*
107 * Read from a stream
108 */
109 size_t DataSource_Stream::read(byte out[], size_t length)
110  {
111  m_source.read(reinterpret_cast<char*>(out), length);
112  if(m_source.bad())
113  throw Stream_IO_Error("DataSource_Stream::read: Source failure");
114 
115  size_t got = m_source.gcount();
116  m_total_read += got;
117  return got;
118  }
119 
120 bool DataSource_Stream::check_available(size_t n)
121  {
122  const std::streampos orig_pos = m_source.tellg();
123  m_source.seekg(0, std::ios::end);
124  const size_t avail = m_source.tellg() - orig_pos;
125  m_source.seekg(orig_pos);
126  return (avail >= n);
127  }
128 
129 /*
130 * Peek into a stream
131 */
132 size_t DataSource_Stream::peek(byte 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<byte> buf(offset);
142  m_source.read(reinterpret_cast<char*>(buf.data()), buf.size());
143  if(m_source.bad())
144  throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
145  got = m_source.gcount();
146  }
147 
148  if(got == offset)
149  {
150  m_source.read(reinterpret_cast<char*>(out), length);
151  if(m_source.bad())
152  throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
153  got = 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 */
166 bool DataSource_Stream::end_of_data() const
167  {
168  return (!m_source.good());
169  }
170 
171 /*
172 * Return a human-readable ID for this stream
173 */
174 std::string DataSource_Stream::id() const
175  {
176  return m_identifier;
177  }
178 
179 /*
180 * DataSource_Stream Constructor
181 */
182 DataSource_Stream::DataSource_Stream(const std::string& path,
183  bool use_binary) :
184  m_identifier(path),
185  m_source_p(new std::ifstream(path,
186  use_binary ? std::ios::binary : std::ios::in)),
187  m_source(*m_source_p),
188  m_total_read(0)
189  {
190  if(!m_source.good())
191  {
192  delete m_source_p;
193  throw Stream_IO_Error("DataSource: Failure opening file " + path);
194  }
195  }
196 
197 /*
198 * DataSource_Stream Constructor
199 */
200 DataSource_Stream::DataSource_Stream(std::istream& in,
201  const std::string& name) :
202  m_identifier(name),
203  m_source_p(nullptr),
204  m_source(in),
205  m_total_read(0)
206  {
207  }
208 
209 /*
210 * DataSource_Stream Destructor
211 */
212 DataSource_Stream::~DataSource_Stream()
213  {
214  delete m_source_p;
215  }
216 
217 #endif
218 
219 }
size_t peek(byte[], size_t, size_t) const override
Definition: data_src.cpp:75
size_t discard_next(size_t N)
Definition: data_src.cpp:38
size_t read(byte[], size_t) override
Definition: data_src.cpp:59
virtual size_t read(byte out[], size_t length) BOTAN_WARN_UNUSED_RESULT=0
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:113
bool end_of_data() const override
Definition: data_src.cpp:89
size_t read_byte(byte &out)
Definition: data_src.cpp:22
size_t peek_byte(byte &out) const
Definition: data_src.cpp:30
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:68
Definition: alg_id.cpp:13
T min(T a, T b)
Definition: ct_utils.h:180
DataSource_Memory(const std::string &in)
Definition: data_src.cpp:97
bool check_available(size_t n) override
Definition: data_src.cpp:67
virtual size_t peek(byte out[], size_t length, size_t peek_offset) const BOTAN_WARN_UNUSED_RESULT=0
std::uint8_t byte
Definition: types.h:31