1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
// queue.h - originally written and placed in the public domain by Wei Dai
/// \file
/// \brief Classes for an unlimited queue to store bytes
#ifndef CRYPTOPP_QUEUE_H
#define CRYPTOPP_QUEUE_H
#include "cryptlib.h"
#include "simple.h"
NAMESPACE_BEGIN(CryptoPP)
class ByteQueueNode;
/// \brief Data structure used to store byte strings
/// \details The queue is implemented as a linked list of byte arrays
class CRYPTOPP_DLL ByteQueue : public Bufferless<BufferedTransformation>
{
public:
/// \brief Construct a ByteQueue
/// \param nodeSize the initial node size
/// \details Internally, ByteQueue uses a ByteQueueNode to store bytes, and \p nodeSize determines the
/// size of the ByteQueueNode. A value of 0 indicates the ByteQueueNode should be automatically sized,
/// which means a value of 256 is used.
ByteQueue(size_t nodeSize=0);
/// \brief Copy construct a ByteQueue
/// \param copy the other ByteQueue
ByteQueue(const ByteQueue ©);
~ByteQueue();
lword MaxRetrievable() const
{return CurrentSize();}
bool AnyRetrievable() const
{return !IsEmpty();}
void IsolatedInitialize(const NameValuePairs ¶meters);
byte * CreatePutSpace(size_t &size);
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
size_t Get(byte &outByte);
size_t Get(byte *outString, size_t getMax);
size_t Peek(byte &outByte) const;
size_t Peek(byte *outString, size_t peekMax) const;
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
// these member functions are not inherited
void SetNodeSize(size_t nodeSize);
lword CurrentSize() const;
bool IsEmpty() const;
void Clear();
void Unget(byte inByte);
void Unget(const byte *inString, size_t length);
const byte * Spy(size_t &contiguousSize) const;
void LazyPut(const byte *inString, size_t size);
void LazyPutModifiable(byte *inString, size_t size);
void UndoLazyPut(size_t size);
void FinalizeLazyPut();
ByteQueue & operator=(const ByteQueue &rhs);
bool operator==(const ByteQueue &rhs) const;
bool operator!=(const ByteQueue &rhs) const {return !operator==(rhs);}
byte operator[](lword i) const;
void swap(ByteQueue &rhs);
/// \brief A ByteQueue iterator
class Walker : public InputRejecting<BufferedTransformation>
{
public:
/// \brief Construct a ByteQueue Walker
/// \param queue a ByteQueue
Walker(const ByteQueue &queue)
: m_queue(queue), m_node(NULLPTR), m_position(0), m_offset(0), m_lazyString(NULLPTR), m_lazyLength(0)
{Initialize();}
lword GetCurrentPosition() {return m_position;}
lword MaxRetrievable() const
{return m_queue.CurrentSize() - m_position;}
void IsolatedInitialize(const NameValuePairs ¶meters);
size_t Get(byte &outByte);
size_t Get(byte *outString, size_t getMax);
size_t Peek(byte &outByte) const;
size_t Peek(byte *outString, size_t peekMax) const;
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
private:
const ByteQueue &m_queue;
const ByteQueueNode *m_node;
lword m_position;
size_t m_offset;
const byte *m_lazyString;
size_t m_lazyLength;
};
friend class Walker;
private:
void CleanupUsedNodes();
void CopyFrom(const ByteQueue ©);
void Destroy();
bool m_autoNodeSize;
size_t m_nodeSize;
ByteQueueNode *m_head, *m_tail;
byte *m_lazyString;
size_t m_lazyLength;
bool m_lazyStringModifiable;
};
/// use this to make sure LazyPut is finalized in event of exception
class CRYPTOPP_DLL LazyPutter
{
public:
LazyPutter(ByteQueue &bq, const byte *inString, size_t size)
: m_bq(bq) {bq.LazyPut(inString, size);}
~LazyPutter()
{try {m_bq.FinalizeLazyPut();} catch(const Exception&) {CRYPTOPP_ASSERT(0);}}
protected:
LazyPutter(ByteQueue &bq) : m_bq(bq) {}
private:
ByteQueue &m_bq;
};
/// like LazyPutter, but does a LazyPutModifiable instead
class LazyPutterModifiable : public LazyPutter
{
public:
LazyPutterModifiable(ByteQueue &bq, byte *inString, size_t size)
: LazyPutter(bq) {bq.LazyPutModifiable(inString, size);}
};
NAMESPACE_END
#ifndef __BORLANDC__
NAMESPACE_BEGIN(std)
template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b)
{
a.swap(b);
}
NAMESPACE_END
#endif
#endif
|