Coverage Report

Created: 2021-11-25 09:31

/src/botan/src/lib/utils/data_src.cpp
Line
Count
Source (jump to first uncovered line)
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
32.1M
   {
25
32.1M
   return read(&out, 1);
26
32.1M
   }
27
28
/*
29
* Peek a single byte from the DataSource
30
*/
31
size_t DataSource::peek_byte(uint8_t& out) const
32
37.6k
   {
33
37.6k
   return peek(&out, 1, 0);
34
37.6k
   }
35
36
/*
37
* Discard the next N bytes of the data
38
*/
39
size_t DataSource::discard_next(size_t n)
40
1.05M
   {
41
1.05M
   uint8_t buf[64] = { 0 };
42
1.05M
   size_t discarded = 0;
43
44
4.20M
   while(n)
45
3.14M
      {
46
3.14M
      const size_t got = this->read(buf, std::min(n, sizeof(buf)));
47
3.14M
      discarded += got;
48
3.14M
      n -= got;
49
50
3.14M
      if(got == 0)
51
2.26k
         break;
52
3.14M
      }
53
54
1.05M
   return discarded;
55
1.05M
   }
56
57
/*
58
* Read from a memory buffer
59
*/
60
size_t DataSource_Memory::read(uint8_t out[], size_t length)
61
19.2M
   {
62
19.2M
   const size_t got = std::min<size_t>(m_source.size() - m_offset, length);
63
19.2M
   copy_mem(out, m_source.data() + m_offset, got);
64
19.2M
   m_offset += got;
65
19.2M
   return got;
66
19.2M
   }
67
68
bool DataSource_Memory::check_available(size_t n)
69
513k
   {
70
513k
   return (n <= (m_source.size() - m_offset));
71
513k
   }
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
673k
   {
79
673k
   const size_t bytes_left = m_source.size() - m_offset;
80
673k
   if(peek_offset >= bytes_left) return 0;
81
82
434k
   const size_t got = std::min(bytes_left - peek_offset, length);
83
434k
   copy_mem(out, &m_source[m_offset + peek_offset], got);
84
434k
   return got;
85
673k
   }
86
87
/*
88
* Check if the memory buffer is empty
89
*/
90
bool DataSource_Memory::end_of_data() const
91
1.78M
   {
92
1.78M
   return (m_offset == m_source.size());
93
1.78M
   }
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
11.1k
   {
103
11.1k
   }
104
105
/*
106
* Read from a stream
107
*/
108
size_t DataSource_Stream::read(uint8_t out[], size_t length)
109
0
   {
110
0
   m_source.read(cast_uint8_ptr_to_char(out), length);
111
0
   if(m_source.bad())
112
0
      throw Stream_IO_Error("DataSource_Stream::read: Source failure");
113
114
0
   const size_t got = static_cast<size_t>(m_source.gcount());
115
0
   m_total_read += got;
116
0
   return got;
117
0
   }
118
119
bool DataSource_Stream::check_available(size_t n)
120
0
   {
121
0
   const std::streampos orig_pos = m_source.tellg();
122
0
   m_source.seekg(0, std::ios::end);
123
0
   const size_t avail = static_cast<size_t>(m_source.tellg() - orig_pos);
124
0
   m_source.seekg(orig_pos);
125
0
   return (avail >= n);
126
0
   }
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
0
   {
133
0
   if(end_of_data())
134
0
      throw Invalid_State("DataSource_Stream: Cannot peek when out of data");
135
136
0
   size_t got = 0;
137
138
0
   if(offset)
139
0
      {
140
0
      secure_vector<uint8_t> buf(offset);
141
0
      m_source.read(cast_uint8_ptr_to_char(buf.data()), buf.size());
142
0
      if(m_source.bad())
143
0
         throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
144
0
      got = static_cast<size_t>(m_source.gcount());
145
0
      }
146
147
0
   if(got == offset)
148
0
      {
149
0
      m_source.read(cast_uint8_ptr_to_char(out), length);
150
0
      if(m_source.bad())
151
0
         throw Stream_IO_Error("DataSource_Stream::peek: Source failure");
152
0
      got = static_cast<size_t>(m_source.gcount());
153
0
      }
154
155
0
   if(m_source.eof())
156
0
      m_source.clear();
157
0
   m_source.seekg(m_total_read, std::ios::beg);
158
159
0
   return got;
160
0
   }
161
162
/*
163
* Check if the stream is empty or in error
164
*/
165
bool DataSource_Stream::end_of_data() const
166
0
   {
167
0
   return (!m_source.good());
168
0
   }
169
170
/*
171
* Return a human-readable ID for this stream
172
*/
173
std::string DataSource_Stream::id() const
174
0
   {
175
0
   return m_identifier;
176
0
   }
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
0
   {
190
0
   if(!m_source.good())
191
0
      {
192
0
      throw Stream_IO_Error("DataSource: Failure opening file " + path);
193
0
      }
194
0
   }
195
196
#endif
197
198
/*
199
* DataSource_Stream Constructor
200
*/
201
DataSource_Stream::DataSource_Stream(std::istream& in,
202
                                     const std::string& name) :
203
   m_identifier(name),
204
   m_source(in),
205
   m_total_read(0)
206
0
   {
207
0
   }
208
209
DataSource_Stream::~DataSource_Stream()
210
0
   {
211
   // for ~unique_ptr
212
0
   }
213
214
}