?? filters.cpp
字號:
// filters.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#include "filters.h"
#include "mqueue.h"
#include "fltrimpl.h"
#include "argnames.h"
#include <memory>
#include <functional>
NAMESPACE_BEGIN(CryptoPP)
Filter::Filter(BufferedTransformation *attachment)
: m_attachment(attachment), m_continueAt(0)
{
}
BufferedTransformation * Filter::NewDefaultAttachment() const
{
return new MessageQueue;
}
BufferedTransformation * Filter::AttachedTransformation()
{
if (m_attachment.get() == NULL)
m_attachment.reset(NewDefaultAttachment());
return m_attachment.get();
}
const BufferedTransformation *Filter::AttachedTransformation() const
{
if (m_attachment.get() == NULL)
const_cast<Filter *>(this)->m_attachment.reset(NewDefaultAttachment());
return m_attachment.get();
}
void Filter::Detach(BufferedTransformation *newOut)
{
m_attachment.reset(newOut);
NotifyAttachmentChange();
}
void Filter::Insert(Filter *filter)
{
filter->m_attachment.reset(m_attachment.release());
m_attachment.reset(filter);
NotifyAttachmentChange();
}
unsigned int Filter::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
{
return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking);
}
unsigned int Filter::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
{
return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking);
}
void Filter::Initialize(const NameValuePairs ¶meters, int propagation)
{
m_continueAt = 0;
IsolatedInitialize(parameters);
PropagateInitialize(parameters, propagation);
}
bool Filter::Flush(bool hardFlush, int propagation, bool blocking)
{
switch (m_continueAt)
{
case 0:
if (IsolatedFlush(hardFlush, blocking))
return true;
case 1:
if (OutputFlush(1, hardFlush, propagation, blocking))
return true;
}
return false;
}
bool Filter::MessageSeriesEnd(int propagation, bool blocking)
{
switch (m_continueAt)
{
case 0:
if (IsolatedMessageSeriesEnd(blocking))
return true;
case 1:
if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking))
return true;
}
return false;
}
void Filter::PropagateInitialize(const NameValuePairs ¶meters, int propagation, const std::string &channel)
{
if (propagation)
AttachedTransformation()->ChannelInitialize(channel, parameters, propagation-1);
}
unsigned int Filter::Output(int outputSite, const byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string &channel)
{
if (messageEnd)
messageEnd--;
unsigned int result = AttachedTransformation()->Put2(inString, length, messageEnd, blocking);
m_continueAt = result ? outputSite : 0;
return result;
}
bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel)
{
if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking))
{
m_continueAt = outputSite;
return true;
}
m_continueAt = 0;
return false;
}
bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel)
{
if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking))
{
m_continueAt = outputSite;
return true;
}
m_continueAt = 0;
return false;
}
// *************************************************************
unsigned int MeterFilter::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
{
FILTER_BEGIN;
m_currentMessageBytes += length;
m_totalBytes += length;
if (messageEnd)
{
m_currentMessageBytes = 0;
m_currentSeriesMessages++;
m_totalMessages++;
}
FILTER_OUTPUT(1, begin, length, messageEnd);
FILTER_END;
}
bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking)
{
m_currentMessageBytes = 0;
m_currentSeriesMessages = 0;
m_totalMessageSeries++;
return false;
}
// *************************************************************
void FilterWithBufferedInput::BlockQueue::ResetQueue(unsigned int blockSize, unsigned int maxBlocks)
{
m_buffer.New(blockSize * maxBlocks);
m_blockSize = blockSize;
m_maxBlocks = maxBlocks;
m_size = 0;
m_begin = m_buffer;
}
byte *FilterWithBufferedInput::BlockQueue::GetBlock()
{
if (m_size >= m_blockSize)
{
byte *ptr = m_begin;
if ((m_begin+=m_blockSize) == m_buffer.end())
m_begin = m_buffer;
m_size -= m_blockSize;
return ptr;
}
else
return NULL;
}
byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(unsigned int &numberOfBytes)
{
numberOfBytes = STDMIN(numberOfBytes, STDMIN((unsigned int)(m_buffer.end()-m_begin), m_size));
byte *ptr = m_begin;
m_begin += numberOfBytes;
m_size -= numberOfBytes;
if (m_size == 0 || m_begin == m_buffer.end())
m_begin = m_buffer;
return ptr;
}
unsigned int FilterWithBufferedInput::BlockQueue::GetAll(byte *outString)
{
unsigned int size = m_size;
unsigned int numberOfBytes = m_maxBlocks*m_blockSize;
const byte *ptr = GetContigousBlocks(numberOfBytes);
memcpy(outString, ptr, numberOfBytes);
memcpy(outString+numberOfBytes, m_begin, m_size);
m_size = 0;
return size;
}
void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, unsigned int length)
{
assert(m_size + length <= m_buffer.size());
byte *end = (m_size < (unsigned int)(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size();
unsigned int len = STDMIN(length, (unsigned int)(m_buffer.end()-end));
memcpy(end, inString, len);
if (len < length)
memcpy(m_buffer, inString+len, length-len);
m_size += length;
}
FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment)
: Filter(attachment)
{
}
FilterWithBufferedInput::FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *attachment)
: Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize)
, m_firstInputDone(false)
{
if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
m_queue.ResetQueue(1, m_firstSize);
}
void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs ¶meters)
{
InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize);
if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
m_queue.ResetQueue(1, m_firstSize);
m_firstInputDone = false;
}
bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking)
{
if (!blocking)
throw BlockingInputOnly("FilterWithBufferedInput");
if (hardFlush)
ForceNextPut();
FlushDerived();
return false;
}
unsigned int FilterWithBufferedInput::PutMaybeModifiable(byte *inString, unsigned int length, int messageEnd, bool blocking, bool modifiable)
{
if (!blocking)
throw BlockingInputOnly("FilterWithBufferedInput");
if (length != 0)
{
unsigned int newLength = m_queue.CurrentSize() + length;
if (!m_firstInputDone && newLength >= m_firstSize)
{
unsigned int len = m_firstSize - m_queue.CurrentSize();
m_queue.Put(inString, len);
FirstPut(m_queue.GetContigousBlocks(m_firstSize));
assert(m_queue.CurrentSize() == 0);
m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize);
inString += len;
newLength -= m_firstSize;
m_firstInputDone = true;
}
if (m_firstInputDone)
{
if (m_blockSize == 1)
{
while (newLength > m_lastSize && m_queue.CurrentSize() > 0)
{
unsigned int len = newLength - m_lastSize;
byte *ptr = m_queue.GetContigousBlocks(len);
NextPutModifiable(ptr, len);
newLength -= len;
}
if (newLength > m_lastSize)
{
unsigned int len = newLength - m_lastSize;
NextPutMaybeModifiable(inString, len, modifiable);
inString += len;
newLength -= len;
}
}
else
{
while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
{
NextPutModifiable(m_queue.GetBlock(), m_blockSize);
newLength -= m_blockSize;
}
if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0)
{
assert(m_queue.CurrentSize() < m_blockSize);
unsigned int len = m_blockSize - m_queue.CurrentSize();
m_queue.Put(inString, len);
inString += len;
NextPutModifiable(m_queue.GetBlock(), m_blockSize);
newLength -= m_blockSize;
}
if (newLength >= m_blockSize + m_lastSize)
{
unsigned int len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize);
NextPutMaybeModifiable(inString, len, modifiable);
inString += len;
newLength -= len;
}
}
}
m_queue.Put(inString, newLength - m_queue.CurrentSize());
}
if (messageEnd)
{
if (!m_firstInputDone && m_firstSize==0)
FirstPut(NULL);
SecByteBlock temp(m_queue.CurrentSize());
m_queue.GetAll(temp);
LastPut(temp, temp.size());
m_firstInputDone = false;
m_queue.ResetQueue(1, m_firstSize);
Output(1, NULL, 0, messageEnd, blocking);
}
return 0;
}
void FilterWithBufferedInput::ForceNextPut()
{
if (!m_firstInputDone)
return;
if (m_blockSize > 1)
{
while (m_queue.CurrentSize() >= m_blockSize)
NextPutModifiable(m_queue.GetBlock(), m_blockSize);
}
else
{
unsigned int len;
while ((len = m_queue.CurrentSize()) > 0)
NextPutModifiable(m_queue.GetContigousBlocks(len), len);
}
}
void FilterWithBufferedInput::NextPutMultiple(const byte *inString, unsigned int length)
{
assert(m_blockSize > 1); // m_blockSize = 1 should always override this function
while (length > 0)
{
assert(length >= m_blockSize);
NextPutSingle(inString);
inString += m_blockSize;
length -= m_blockSize;
}
}
// *************************************************************
void Redirector::ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters, int propagation)
{
if (channel.empty())
{
m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL);
m_passSignal = parameters.GetValueWithDefault("PassSignal", true);
}
if (m_target && m_passSignal)
m_target->ChannelInitialize(channel, parameters, propagation);
}
// *************************************************************
ProxyFilter::ProxyFilter(BufferedTransformation *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *attachment)
: FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter), m_proxy(NULL)
{
if (m_filter.get())
m_filter->Attach(m_proxy = new OutputProxy(*this, false));
}
void ProxyFilter::IsolatedFlush(bool completeFlush)
{
if (m_filter.get())
{
bool passSignal = m_proxy->GetPassSignal();
m_proxy->SetPassSignal(false);
m_filter->Flush(completeFlush, -1);
m_proxy->SetPassSignal(passSignal);
}
}
void ProxyFilter::SetFilter(Filter *filter)
{
bool passSignal = m_proxy ? m_proxy->GetPassSignal() : false;
m_filter.reset(filter);
if (filter)
{
std::auto_ptr<OutputProxy> temp(m_proxy = new OutputProxy(*this, passSignal));
m_filter->TransferAllTo(*m_proxy);
m_filter->Attach(temp.release());
}
else
m_proxy=NULL;
}
void ProxyFilter::NextPutMultiple(const byte *s, unsigned int len)
{
if (m_filter.get())
m_filter->Put(s, len);
}
// *************************************************************
unsigned int ArraySink::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
{
memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
m_total += length;
return 0;
}
byte * ArraySink::CreatePutSpace(unsigned int &size)
{
size = m_size - m_total;
return m_buf + m_total;
}
void ArraySink::IsolatedInitialize(const NameValuePairs ¶meters)
{
ByteArrayParameter array;
if (!parameters.GetValue(Name::OutputBuffer(), array))
throw InvalidArgument("ArraySink: missing OutputBuffer argument");
m_buf = array.begin();
m_size = array.size();
m_total = 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -