Botan  2.4.0
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 #include <istream>
13 
14 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
15  #include <fstream>
16 #endif
17 
18 namespace Botan {
19 
20 /*
21 * Read a single byte from the DataSource
22 */
23 size_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 */
31 size_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 */
39 size_t DataSource::discard_next(size_t n)
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 */
60 size_t DataSource_Memory::read(uint8_t out[], size_t length)
61  {
62  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 */
76 size_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  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 */
98 DataSource_Memory::DataSource_Memory(const std::string& in) :
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 */
108 size_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 */
131 size_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 */
173 std::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 */
183 DataSource_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 }
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
size_t discard_next(size_t N)
Definition: data_src.cpp:39
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:120
std::string id() const override
Definition: data_src.cpp:173
virtual size_t peek(uint8_t out[], size_t length, size_t peek_offset) const BOTAN_WARN_UNUSED_RESULT=0
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:90
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:97
Definition: alg_id.cpp:13
size_t read_byte(uint8_t &out)
Definition: data_src.cpp:23
size_t peek_byte(uint8_t &out) const
Definition: data_src.cpp:31
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition: mem_ops.h:125
bool end_of_data() const override
Definition: data_src.cpp:165
DataSource_Memory(const std::string &in)
Definition: data_src.cpp:98
size_t peek(uint8_t[], size_t, size_t) const override
Definition: data_src.cpp:76
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
bool check_available(size_t n) override
Definition: data_src.cpp:68
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:131