Botan  1.11.33
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 */
22 size_t DataSource::read_byte(uint8_t& out)
23  {
24  return read(&out, 1);
25  }
26 
27 /*
28 * Peek a single byte from the DataSource
29 */
30 size_t DataSource::peek_byte(uint8_t& 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  uint8_t 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(uint8_t 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(uint8_t 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 uint8_t*>(in.data()),
99  reinterpret_cast<const uint8_t*>(in.data()) + in.length()),
100  m_offset(0)
101  {
102  }
103 
104 /*
105 * Read from a stream
106 */
107 size_t DataSource_Stream::read(uint8_t out[], size_t length)
108  {
109  m_source.read(reinterpret_cast<char*>(out), length);
110  if(m_source.bad())
111  throw Stream_IO_Error("DataSource_Stream::read: Source failure");
112 
113  size_t got = m_source.gcount();
114  m_total_read += got;
115  return got;
116  }
117 
119  {
120  const std::streampos orig_pos = m_source.tellg();
121  m_source.seekg(0, std::ios::end);
122  const size_t avail = m_source.tellg() - orig_pos;
123  m_source.seekg(orig_pos);
124  return (avail >= n);
125  }
126 
127 /*
128 * Peek into a stream
129 */
130 size_t DataSource_Stream::peek(uint8_t out[], size_t length, size_t offset) const
131  {
132  if(end_of_data())
133  throw Invalid_State("DataSource_Stream: Cannot peek when out of data");
134 
135  size_t got = 0;
136 
137  if(offset)
138  {
139  secure_vector<uint8_t> buf(offset);
140  m_source.read(reinterpret_cast<char*>(buf.data()), buf.size());
141  if(m_source.bad())
142  throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
143  got = m_source.gcount();
144  }
145 
146  if(got == offset)
147  {
148  m_source.read(reinterpret_cast<char*>(out), length);
149  if(m_source.bad())
150  throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
151  got = m_source.gcount();
152  }
153 
154  if(m_source.eof())
155  m_source.clear();
156  m_source.seekg(m_total_read, std::ios::beg);
157 
158  return got;
159  }
160 
161 /*
162 * Check if the stream is empty or in error
163 */
165  {
166  return (!m_source.good());
167  }
168 
169 /*
170 * Return a human-readable ID for this stream
171 */
172 std::string DataSource_Stream::id() const
173  {
174  return m_identifier;
175  }
176 
177 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
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_memory(new std::ifstream(path, use_binary ? std::ios::binary : std::ios::in)),
186  m_source(*m_source_memory),
187  m_total_read(0)
188  {
189  if(!m_source.good())
190  {
191  throw Stream_IO_Error("DataSource: Failure opening file " + path);
192  }
193  }
194 
195 #endif
196 
197 /*
198 * DataSource_Stream Constructor
199 */
201  const std::string& name) :
202  m_identifier(name),
203  m_source(in),
204  m_total_read(0)
205  {
206  }
207 
209  {
210  // for ~unique_ptr
211  }
212 
213 }
bool check_available(size_t n) override
Definition: data_src.cpp:118
size_t read(uint8_t[], size_t) override
Definition: data_src.cpp:107
size_t discard_next(size_t N)
Definition: data_src.cpp:38
std::string id() const override
Definition: data_src.cpp:172
virtual size_t peek(uint8_t out[], size_t length, size_t peek_offset) const BOTAN_WARN_UNUSED_RESULT=0
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:113
DataSource_Stream(std::istream &, const std::string &id="<std::istream>")
Definition: data_src.cpp:200
bool end_of_data() const override
Definition: data_src.cpp:89
virtual size_t read(uint8_t out[], size_t length) BOTAN_WARN_UNUSED_RESULT=0
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:68
Definition: alg_id.cpp:13
size_t read_byte(uint8_t &out)
Definition: data_src.cpp:22
size_t peek_byte(uint8_t &out) const
Definition: data_src.cpp:30
bool end_of_data() const override
Definition: data_src.cpp:164
T min(T a, T b)
Definition: ct_utils.h:180
DataSource_Memory(const std::string &in)
Definition: data_src.cpp:97
size_t peek(uint8_t[], size_t, size_t) const override
Definition: data_src.cpp:75
bool check_available(size_t n) override
Definition: data_src.cpp:67
size_t read(uint8_t[], size_t) override
Definition: data_src.cpp:59
size_t peek(uint8_t[], size_t, size_t) const override
Definition: data_src.cpp:130