Since we have an ArraySink class I thought it would be good to have the
corresponding ArraySource and ArrayStore classes as well:
- Ron
filters.h:
class CRYPTOPP_DLL ArrayStore : public Store, private FilterPutSpaceHelper,
public NotCopyable
{
public:
ArrayStore() : m_data(NULL), m_current(NULL), m_waiting(false),
m_space(NULL), m_len(0) { }
ArrayStore( ArraySink * sink ) : m_waiting(false), m_space(NULL),
m_len(0) {
StoreInitialize(MakeParameters("InputBuffer",
ConstByteArrayParameter(sink->GetBuffer(), sink->GetBufferLength())));
}
ArrayStore(byte *data, unsigned int dataLen) : m_data(NULL),
m_current(NULL), m_waiting(false), m_space(NULL), m_len(0) {
StoreInitialize(MakeParameters("InputBuffer",
ConstByteArrayParameter(data, dataLen)));
}
const byte * GetBuffer() { return m_data; };
unsigned int GetBufferLength() { return m_dataLen; };
unsigned long MaxRetrievable() const;
unsigned int TransferTo2(BufferedTransformation &target, unsigned long
&transferBytes, const std::string &channel=NULL_CHANNEL, bool
blocking=true);
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long
&begin, unsigned long end=ULONG_MAX, const std::string
&channel=NULL_CHANNEL, bool blocking=true) const;
unsigned long Skip(unsigned long skipMax=ULONG_MAX);
private:
void StoreInitialize(const NameValuePairs ¶meters) {
ConstByteArrayParameter array;
if (!parameters.GetValue(Name::InputBuffer(), array))
throw InvalidArgument("StringStore: missing InputBuffer
argument");
m_data= array.begin();
m_current = (byte*) m_data;
m_dataLen = array.size();
m_waiting = false;
};
const byte *m_data;
byte *m_current;
unsigned int m_dataLen;
byte *m_space;
unsigned int m_len;
bool m_waiting;
};
//! array-based implementation of Source interface
class CRYPTOPP_DLL ArraySource : public SourceTemplate<ArrayStore>
{
public:
ArraySource(BufferedTransformation *attachment = NULL) :
SourceTemplate<ArrayStore>(attachment) {}
ArraySource( ArraySink * sink, bool pumpAll, BufferedTransformation
*attachment = NULL ) : SourceTemplate<ArrayStore>(attachment) {
SourceInitialize(pumpAll, MakeParameters("InputBuffer",
ConstByteArrayParameter(sink->GetBuffer(), sink->GetBufferLength())));
}
ArraySource(byte *data, unsigned int dataLen, bool pumpAll,
BufferedTransformation *attachment = NULL) :
SourceTemplate<ArrayStore>(attachment) {
SourceInitialize(pumpAll, MakeParameters("InputBuffer",
ConstByteArrayParameter(data, dataLen)));
}
};
filters.cpp
//! array-based implementation of Source interface
class CRYPTOPP_DLL ArraySource : public SourceTemplate<ArrayStore>
{
public:
ArraySource(BufferedTransformation *attachment = NULL) :
SourceTemplate<ArrayStore>(attachment) {}
ArraySource( ArraySink * sink, bool pumpAll, BufferedTransformation
*attachment = NULL ) : SourceTemplate<ArrayStore>(attachment) {
SourceInitialize(pumpAll, MakeParameters("InputBuffer",
ConstByteArrayParameter(sink->GetBuffer(), sink->GetBufferLength())));
}
ArraySource(byte *data, unsigned int dataLen, bool pumpAll,
BufferedTransformation *attachment = NULL) :
SourceTemplate<ArrayStore>(attachment) {
SourceInitialize(pumpAll, MakeParameters("InputBuffer",
ConstByteArrayParameter(data, dataLen)));
}
};
unsigned long ArrayStore::MaxRetrievable() const
{
if ( (m_dataLen < (m_current-m_data)))
return 0;
return m_dataLen - (m_current-m_data);
}
unsigned int ArrayStore::TransferTo2(BufferedTransformation &target,
unsigned long &transferBytes, const std::string &channel, bool blocking)
{
if (!m_data)
{
transferBytes = 0;
return 0;
}
unsigned long size=transferBytes;
transferBytes = 0;
if (m_waiting)
goto output;
while (size && ( MaxRetrievable()>0 ))
{
unsigned int sz;
{
unsigned int spaceSize = 1024;
m_space = HelpCreatePutSpace(target, channel, 1, (unsigned
int)STDMIN(size, (unsigned long)UINT_MAX), spaceSize);
sz = STDMIN(size, (unsigned long)spaceSize);
sz = STDMIN((unsigned long)sz, (unsigned long)
MaxRetrievable());
memcpy(m_space, m_current, sz);
m_current += sz;
}
m_len = sz;
unsigned int blockedBytes;
output:
blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len,
0, blocking);
m_waiting = blockedBytes > 0;
if (m_waiting)
return blockedBytes;
size -= m_len;
transferBytes += m_len;
}
return 0;
}
unsigned int ArrayStore::CopyRangeTo2(BufferedTransformation &target,
unsigned long &begin, unsigned long end, const std::string &channel, bool
blocking) const
{
if (!m_data)
return 0;
if (begin == 0 && end == 1)
{
if ( MaxRetrievable()==0 )
return 0;
else
{
int result = m_current[0];
unsigned int blockedBytes = target.ChannelPut(channel,
byte(result), blocking);
begin += 1-blockedBytes;
return blockedBytes;
}
}
byte* current = m_current;
byte* endPosition = (byte*)m_data + m_dataLen;
byte* newPosition = current + begin;
if (newPosition >= endPosition)
{
return 0; // don't try to seek beyond the end of file
}
const_cast<ArrayStore *>(this)->Skip(begin);
unsigned long total = 0;
try
{
assert(!m_waiting);
unsigned long copyMax = end-begin;
unsigned int blockedBytes = const_cast<ArrayStore
*>(this)->TransferTo2(target, copyMax, channel, blocking);
begin += copyMax;
if (blockedBytes)
{
const_cast<ArrayStore *>(this)->m_waiting = false;
return blockedBytes;
}
}
catch(...)
{
throw;
}
const_cast<ArrayStore *>(this)->m_current = current;
return 0;
}
unsigned long ArrayStore::Skip(unsigned long skipMax)
{
unsigned long step;
if ( skipMax > MaxRetrievable () )
step = MaxRetrievable();
else
step = skipMax;
m_current += step;
return step;
}
// Contributed by Ron Bessems
//! array-based implementation of Store interface
class CRYPTOPP_DLL ArrayStore : public Store, private FilterPutSpaceHelper,
public NotCopyable
{
public:
ArrayStore() : m_data(NULL), m_current(NULL), m_waiting(false),
m_space(NULL), m_len(0) { }
ArrayStore( ArraySink * sink ) : m_waiting(false), m_space(NULL),
m_len(0) {
StoreInitialize(MakeParameters("InputBuffer",
ConstByteArrayParameter(sink->GetBuffer(), sink->GetBufferLength())));
}
ArrayStore(byte *data, unsigned int dataLen) : m_data(NULL),
m_current(NULL), m_waiting(false), m_space(NULL), m_len(0) {
StoreInitialize(MakeParameters("InputBuffer",
ConstByteArrayParameter(data, dataLen)));
}
const byte * GetBuffer() { return m_data; };
unsigned int GetBufferLength() { return m_dataLen; };
unsigned long MaxRetrievable() const;
unsigned int TransferTo2(BufferedTransformation &target, unsigned long
&transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long
&begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL,
bool blocking=true) const;
unsigned long Skip(unsigned long skipMax=ULONG_MAX);
private:
void StoreInitialize(const NameValuePairs ¶meters) {
ConstByteArrayParameter array;
if (!parameters.GetValue(Name::InputBuffer(), array))
throw InvalidArgument("StringStore: missing InputBuffer
argument");
m_data= array.begin();
m_current = (byte*) m_data;
m_dataLen = array.size();
m_waiting = false;
};
const byte *m_data;
byte *m_current;
unsigned int m_dataLen;
byte *m_space;
unsigned int m_len;
bool m_waiting;
};
//! array-based implementation of Source interface
class CRYPTOPP_DLL ArraySource : public SourceTemplate<ArrayStore>
{
public:
ArraySource(BufferedTransformation *attachment = NULL) :
SourceTemplate<ArrayStore>(attachment) {}
ArraySource( ArraySink * sink, bool pumpAll, BufferedTransformation
*attachment = NULL ) : SourceTemplate<ArrayStore>(attachment) {
SourceInitialize(pumpAll, MakeParameters("InputBuffer",
ConstByteArrayParameter(sink->GetBuffer(), sink->GetBufferLength())));
}
ArraySource(byte *data, unsigned int dataLen, bool pumpAll,
BufferedTransformation *attachment = NULL) :
SourceTemplate<ArrayStore>(attachment) {
SourceInitialize(pumpAll, MakeParameters("InputBuffer",
ConstByteArrayParameter(data, dataLen)));
}
};
unsigned long ArrayStore::MaxRetrievable() const
{
if ( (m_dataLen < (m_current-m_data)))
return 0;
return m_dataLen - (m_current-m_data);
}
unsigned int ArrayStore::TransferTo2(BufferedTransformation &target, unsigned
long &transferBytes, const std::string &channel, bool blocking)
{
if (!m_data)
{
transferBytes = 0;
return 0;
}
unsigned long size=transferBytes;
transferBytes = 0;
if (m_waiting)
goto output;
while (size && ( MaxRetrievable()>0 ))
{
unsigned int sz;
{
unsigned int spaceSize = 1024;
m_space = HelpCreatePutSpace(target, channel, 1,
(unsigned int)STDMIN(size, (unsigned long)UINT_MAX), spaceSize);
sz = STDMIN(size, (unsigned long)spaceSize);
sz = STDMIN((unsigned long)sz, (unsigned long)
MaxRetrievable());
memcpy(m_space, m_current, sz);
m_current += sz;
}
m_len = sz;
unsigned int blockedBytes;
output:
blockedBytes = target.ChannelPutModifiable2(channel, m_space,
m_len, 0, blocking);
m_waiting = blockedBytes > 0;
if (m_waiting)
return blockedBytes;
size -= m_len;
transferBytes += m_len;
}
return 0;
}
unsigned int ArrayStore::CopyRangeTo2(BufferedTransformation &target, unsigned
long &begin, unsigned long end, const std::string &channel, bool blocking) const
{
if (!m_data)
return 0;
if (begin == 0 && end == 1)
{
if ( MaxRetrievable()==0 )
return 0;
else
{
int result = m_current[0];
unsigned int blockedBytes = target.ChannelPut(channel,
byte(result), blocking);
begin += 1-blockedBytes;
return blockedBytes;
}
}
byte* current = m_current;
byte* endPosition = (byte*)m_data + m_dataLen;
byte* newPosition = current + begin;
if (newPosition >= endPosition)
{
return 0; // don't try to seek beyond the end of file
}
const_cast<ArrayStore *>(this)->Skip(begin);
unsigned long total = 0;
try
{
assert(!m_waiting);
unsigned long copyMax = end-begin;
unsigned int blockedBytes = const_cast<ArrayStore
*>(this)->TransferTo2(target, copyMax, channel, blocking);
begin += copyMax;
if (blockedBytes)
{
const_cast<ArrayStore *>(this)->m_waiting = false;
return blockedBytes;
}
}
catch(...)
{
throw;
}
const_cast<ArrayStore *>(this)->m_current = current;
return 0;
}
unsigned long ArrayStore::Skip(unsigned long skipMax)
{
unsigned long step;
if ( skipMax > MaxRetrievable () )
step = MaxRetrievable();
else
step = skipMax;
m_current += step;
return step;
}