Botan  1.11.15
src/lib/filters/buf_filt.cpp
Go to the documentation of this file.
00001 /*
00002 * Buffered Filter
00003 * (C) 1999-2007 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/buf_filt.h>
00009 #include <botan/mem_ops.h>
00010 #include <botan/internal/rounding.h>
00011 #include <stdexcept>
00012 
00013 namespace Botan {
00014 
00015 /*
00016 * Buffered_Filter Constructor
00017 */
00018 Buffered_Filter::Buffered_Filter(size_t b, size_t f) :
00019    main_block_mod(b), final_minimum(f)
00020    {
00021    if(main_block_mod == 0)
00022       throw std::invalid_argument("main_block_mod == 0");
00023 
00024    if(final_minimum > main_block_mod)
00025       throw std::invalid_argument("final_minimum > main_block_mod");
00026 
00027    buffer.resize(2 * main_block_mod);
00028    buffer_pos = 0;
00029    }
00030 
00031 /*
00032 * Buffer input into blocks, trying to minimize copying
00033 */
00034 void Buffered_Filter::write(const byte input[], size_t input_size)
00035    {
00036    if(!input_size)
00037       return;
00038 
00039    if(buffer_pos + input_size >= main_block_mod + final_minimum)
00040       {
00041       size_t to_copy = std::min<size_t>(buffer.size() - buffer_pos, input_size);
00042 
00043       copy_mem(&buffer[buffer_pos], input, to_copy);
00044       buffer_pos += to_copy;
00045 
00046       input += to_copy;
00047       input_size -= to_copy;
00048 
00049       size_t total_to_consume =
00050          round_down(std::min(buffer_pos,
00051                              buffer_pos + input_size - final_minimum),
00052                     main_block_mod);
00053 
00054       buffered_block(&buffer[0], total_to_consume);
00055 
00056       buffer_pos -= total_to_consume;
00057 
00058       copy_mem(&buffer[0], &buffer[0] + total_to_consume, buffer_pos);
00059       }
00060 
00061    if(input_size >= final_minimum)
00062       {
00063       size_t full_blocks = (input_size - final_minimum) / main_block_mod;
00064       size_t to_copy = full_blocks * main_block_mod;
00065 
00066       if(to_copy)
00067          {
00068          buffered_block(input, to_copy);
00069 
00070          input += to_copy;
00071          input_size -= to_copy;
00072          }
00073       }
00074 
00075    copy_mem(&buffer[buffer_pos], input, input_size);
00076    buffer_pos += input_size;
00077    }
00078 
00079 /*
00080 * Finish/flush operation
00081 */
00082 void Buffered_Filter::end_msg()
00083    {
00084    if(buffer_pos < final_minimum)
00085       throw std::runtime_error("Buffered filter end_msg without enough input");
00086 
00087    size_t spare_blocks = (buffer_pos - final_minimum) / main_block_mod;
00088 
00089    if(spare_blocks)
00090       {
00091       size_t spare_bytes = main_block_mod * spare_blocks;
00092       buffered_block(&buffer[0], spare_bytes);
00093       buffered_final(&buffer[spare_bytes], buffer_pos - spare_bytes);
00094       }
00095    else
00096       {
00097       buffered_final(&buffer[0], buffer_pos);
00098       }
00099 
00100    buffer_pos = 0;
00101    }
00102 
00103 }