Botan  2.8.0
Crypto and TLS for C++11
buf_filt.cpp
Go to the documentation of this file.
1 /*
2 * Buffered Filter
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/buf_filt.h>
9 #include <botan/mem_ops.h>
10 #include <botan/internal/rounding.h>
11 #include <botan/exceptn.h>
12 
13 namespace Botan {
14 
15 /*
16 * Buffered_Filter Constructor
17 */
18 Buffered_Filter::Buffered_Filter(size_t b, size_t f) :
19  m_main_block_mod(b), m_final_minimum(f)
20  {
21  if(m_main_block_mod == 0)
22  throw Invalid_Argument("m_main_block_mod == 0");
23 
24  if(m_final_minimum > m_main_block_mod)
25  throw Invalid_Argument("m_final_minimum > m_main_block_mod");
26 
27  m_buffer.resize(2 * m_main_block_mod);
28  m_buffer_pos = 0;
29  }
30 
31 /*
32 * Buffer input into blocks, trying to minimize copying
33 */
34 void Buffered_Filter::write(const uint8_t input[], size_t input_size)
35  {
36  if(!input_size)
37  return;
38 
39  if(m_buffer_pos + input_size >= m_main_block_mod + m_final_minimum)
40  {
41  size_t to_copy = std::min<size_t>(m_buffer.size() - m_buffer_pos, input_size);
42 
43  copy_mem(&m_buffer[m_buffer_pos], input, to_copy);
44  m_buffer_pos += to_copy;
45 
46  input += to_copy;
47  input_size -= to_copy;
48 
49  size_t total_to_consume =
50  round_down(std::min(m_buffer_pos,
51  m_buffer_pos + input_size - m_final_minimum),
52  m_main_block_mod);
53 
54  buffered_block(m_buffer.data(), total_to_consume);
55 
56  m_buffer_pos -= total_to_consume;
57 
58  copy_mem(m_buffer.data(), m_buffer.data() + total_to_consume, m_buffer_pos);
59  }
60 
61  if(input_size >= m_final_minimum)
62  {
63  size_t full_blocks = (input_size - m_final_minimum) / m_main_block_mod;
64  size_t to_copy = full_blocks * m_main_block_mod;
65 
66  if(to_copy)
67  {
68  buffered_block(input, to_copy);
69 
70  input += to_copy;
71  input_size -= to_copy;
72  }
73  }
74 
75  copy_mem(&m_buffer[m_buffer_pos], input, input_size);
76  m_buffer_pos += input_size;
77  }
78 
79 /*
80 * Finish/flush operation
81 */
83  {
84  if(m_buffer_pos < m_final_minimum)
85  throw Exception("Buffered filter end_msg without enough input");
86 
87  size_t spare_blocks = (m_buffer_pos - m_final_minimum) / m_main_block_mod;
88 
89  if(spare_blocks)
90  {
91  size_t spare_bytes = m_main_block_mod * spare_blocks;
92  buffered_block(m_buffer.data(), spare_bytes);
93  buffered_final(&m_buffer[spare_bytes], m_buffer_pos - spare_bytes);
94  }
95  else
96  {
97  buffered_final(m_buffer.data(), m_buffer_pos);
98  }
99 
100  m_buffer_pos = 0;
101  }
102 
103 }
T round_down(T n, T align_to)
Definition: rounding.h:37
virtual void buffered_block(const uint8_t input[], size_t length)=0
void write(const uint8_t in[], size_t length)
Definition: buf_filt.cpp:34
virtual void buffered_final(const uint8_t input[], size_t length)=0
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
Definition: alg_id.cpp:13
Buffered_Filter(size_t block_size, size_t final_minimum)
Definition: buf_filt.cpp:18