1
// queue.cpp - written and placed in the public domain by Wei Dai
5
#ifndef CRYPTOPP_IMPORTS
10
NAMESPACE_BEGIN(CryptoPP)
12
static const unsigned int s_maxAutoNodeSize = 16*1024;
14
// this class for use by ByteQueue only
18
ByteQueueNode(size_t maxSize)
25
inline size_t MaxSize() const {return buf.size();}
27
inline size_t CurrentSize() const
32
inline bool UsedUp() const
34
return (m_head==MaxSize());
42
inline size_t Put(const byte *begin, size_t length)
44
size_t l = STDMIN(length, MaxSize()-m_tail);
45
if (buf+m_tail != begin)
46
memcpy(buf+m_tail, begin, l);
51
inline size_t Peek(byte &outByte) const
60
inline size_t Peek(byte *target, size_t copyMax) const
62
size_t len = STDMIN(copyMax, m_tail-m_head);
63
memcpy(target, buf+m_head, len);
67
inline size_t CopyTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const
69
size_t len = m_tail-m_head;
70
target.ChannelPut(channel, buf+m_head, len);
74
inline size_t CopyTo(BufferedTransformation &target, size_t copyMax, const std::string &channel=DEFAULT_CHANNEL) const
76
size_t len = STDMIN(copyMax, m_tail-m_head);
77
target.ChannelPut(channel, buf+m_head, len);
81
inline size_t Get(byte &outByte)
83
size_t len = Peek(outByte);
88
inline size_t Get(byte *outString, size_t getMax)
90
size_t len = Peek(outString, getMax);
95
inline size_t TransferTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL)
97
size_t len = m_tail-m_head;
98
target.ChannelPutModifiable(channel, buf+m_head, len);
103
inline size_t TransferTo(BufferedTransformation &target, lword transferMax, const std::string &channel=DEFAULT_CHANNEL)
105
size_t len = UnsignedMin(m_tail-m_head, transferMax);
106
target.ChannelPutModifiable(channel, buf+m_head, len);
111
inline size_t Skip(size_t skipMax)
113
size_t len = STDMIN(skipMax, m_tail-m_head);
118
inline byte operator[](size_t i) const
120
return buf[m_head+i];
126
size_t m_head, m_tail;
129
// ********************************************************
131
ByteQueue::ByteQueue(size_t nodeSize)
134
SetNodeSize(nodeSize);
135
m_head = m_tail = new ByteQueueNode(m_nodeSize);
138
void ByteQueue::SetNodeSize(size_t nodeSize)
140
m_autoNodeSize = !nodeSize;
141
m_nodeSize = m_autoNodeSize ? 256 : nodeSize;
144
ByteQueue::ByteQueue(const ByteQueue ©)
149
void ByteQueue::CopyFrom(const ByteQueue ©)
152
m_autoNodeSize = copy.m_autoNodeSize;
153
m_nodeSize = copy.m_nodeSize;
154
m_head = m_tail = new ByteQueueNode(*copy.m_head);
156
for (ByteQueueNode *current=copy.m_head->next; current; current=current->next)
158
m_tail->next = new ByteQueueNode(*current);
159
m_tail = m_tail->next;
164
Put(copy.m_lazyString, copy.m_lazyLength);
167
ByteQueue::~ByteQueue()
172
void ByteQueue::Destroy()
174
for (ByteQueueNode *next, *current=m_head; current; current=next)
181
void ByteQueue::IsolatedInitialize(const NameValuePairs ¶meters)
183
m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256);
187
lword ByteQueue::CurrentSize() const
191
for (ByteQueueNode *current=m_head; current; current=current->next)
192
size += current->CurrentSize();
194
return size + m_lazyLength;
197
bool ByteQueue::IsEmpty() const
199
return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0;
202
void ByteQueue::Clear()
204
for (ByteQueueNode *next, *current=m_head->next; current; current=next)
216
size_t ByteQueue::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
218
if (m_lazyLength > 0)
222
while ((len=m_tail->Put(inString, length)) < length)
226
if (m_autoNodeSize && m_nodeSize < s_maxAutoNodeSize)
231
while (m_nodeSize < length && m_nodeSize < s_maxAutoNodeSize);
232
m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, length));
233
m_tail = m_tail->next;
239
void ByteQueue::CleanupUsedNodes()
241
while (m_head != m_tail && m_head->UsedUp())
243
ByteQueueNode *temp=m_head;
248
if (m_head->CurrentSize() == 0)
252
void ByteQueue::LazyPut(const byte *inString, size_t size)
254
if (m_lazyLength > 0)
257
if (inString == m_tail->buf+m_tail->m_tail)
261
m_lazyString = const_cast<byte *>(inString);
263
m_lazyStringModifiable = false;
267
void ByteQueue::LazyPutModifiable(byte *inString, size_t size)
269
if (m_lazyLength > 0)
271
m_lazyString = inString;
273
m_lazyStringModifiable = true;
276
void ByteQueue::UndoLazyPut(size_t size)
278
if (m_lazyLength < size)
279
throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large");
281
m_lazyLength -= size;
284
void ByteQueue::FinalizeLazyPut()
286
size_t len = m_lazyLength;
289
Put(m_lazyString, len);
292
size_t ByteQueue::Get(byte &outByte)
294
if (m_head->Get(outByte))
296
if (m_head->UsedUp())
300
else if (m_lazyLength > 0)
302
outByte = *m_lazyString++;
310
size_t ByteQueue::Get(byte *outString, size_t getMax)
312
ArraySink sink(outString, getMax);
313
return (size_t)TransferTo(sink, getMax);
316
size_t ByteQueue::Peek(byte &outByte) const
318
if (m_head->Peek(outByte))
320
else if (m_lazyLength > 0)
322
outByte = *m_lazyString;
329
size_t ByteQueue::Peek(byte *outString, size_t peekMax) const
331
ArraySink sink(outString, peekMax);
332
return (size_t)CopyTo(sink, peekMax);
335
size_t ByteQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
339
lword bytesLeft = transferBytes;
340
for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
341
bytesLeft -= current->TransferTo(target, bytesLeft, channel);
344
size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
347
if (m_lazyStringModifiable)
348
target.ChannelPutModifiable(channel, m_lazyString, len);
350
target.ChannelPut(channel, m_lazyString, len);
355
transferBytes -= bytesLeft;
360
Walker walker(*this);
361
size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
367
size_t ByteQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
369
Walker walker(*this);
371
lword transferBytes = end-begin;
372
size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
373
begin += transferBytes;
377
void ByteQueue::Unget(byte inByte)
382
void ByteQueue::Unget(const byte *inString, size_t length)
384
size_t len = STDMIN(length, m_head->m_head);
386
m_head->m_head -= len;
387
memcpy(m_head->buf + m_head->m_head, inString + length, len);
391
ByteQueueNode *newHead = new ByteQueueNode(length);
392
newHead->next = m_head;
394
m_head->Put(inString, length);
398
const byte * ByteQueue::Spy(size_t &contiguousSize) const
400
contiguousSize = m_head->m_tail - m_head->m_head;
401
if (contiguousSize == 0 && m_lazyLength > 0)
403
contiguousSize = m_lazyLength;
407
return m_head->buf + m_head->m_head;
410
byte * ByteQueue::CreatePutSpace(size_t &size)
412
if (m_lazyLength > 0)
415
if (m_tail->m_tail == m_tail->MaxSize())
417
m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, size));
418
m_tail = m_tail->next;
421
size = m_tail->MaxSize() - m_tail->m_tail;
422
return m_tail->buf + m_tail->m_tail;
425
ByteQueue & ByteQueue::operator=(const ByteQueue &rhs)
432
bool ByteQueue::operator==(const ByteQueue &rhs) const
434
const lword currentSize = CurrentSize();
436
if (currentSize != rhs.CurrentSize())
439
Walker walker1(*this), walker2(rhs);
442
while (walker1.Get(b1) && walker2.Get(b2))
449
byte ByteQueue::operator[](lword i) const
451
for (ByteQueueNode *current=m_head; current; current=current->next)
453
if (i < current->CurrentSize())
454
return (*current)[(size_t)i];
456
i -= current->CurrentSize();
459
assert(i < m_lazyLength);
460
return m_lazyString[i];
463
void ByteQueue::swap(ByteQueue &rhs)
465
std::swap(m_autoNodeSize, rhs.m_autoNodeSize);
466
std::swap(m_nodeSize, rhs.m_nodeSize);
467
std::swap(m_head, rhs.m_head);
468
std::swap(m_tail, rhs.m_tail);
469
std::swap(m_lazyString, rhs.m_lazyString);
470
std::swap(m_lazyLength, rhs.m_lazyLength);
471
std::swap(m_lazyStringModifiable, rhs.m_lazyStringModifiable);
474
// ********************************************************
476
void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs ¶meters)
478
m_node = m_queue.m_head;
481
m_lazyString = m_queue.m_lazyString;
482
m_lazyLength = m_queue.m_lazyLength;
485
size_t ByteQueue::Walker::Get(byte &outByte)
487
ArraySink sink(&outByte, 1);
488
return (size_t)TransferTo(sink, 1);
491
size_t ByteQueue::Walker::Get(byte *outString, size_t getMax)
493
ArraySink sink(outString, getMax);
494
return (size_t)TransferTo(sink, getMax);
497
size_t ByteQueue::Walker::Peek(byte &outByte) const
499
ArraySink sink(&outByte, 1);
500
return (size_t)CopyTo(sink, 1);
503
size_t ByteQueue::Walker::Peek(byte *outString, size_t peekMax) const
505
ArraySink sink(outString, peekMax);
506
return (size_t)CopyTo(sink, peekMax);
509
size_t ByteQueue::Walker::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
511
lword bytesLeft = transferBytes;
512
size_t blockedBytes = 0;
516
size_t len = (size_t)STDMIN(bytesLeft, (lword)m_node->CurrentSize()-m_offset);
517
blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking);
531
m_node = m_node->next;
535
if (bytesLeft && m_lazyLength)
537
size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
538
blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking);
548
transferBytes -= bytesLeft;
552
size_t ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
554
Walker walker(*this);
556
lword transferBytes = end-begin;
557
size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
558
begin += transferBytes;