5 #ifndef CRYPTOPP_IMPORTS
10 NAMESPACE_BEGIN(CryptoPP)
12 static const
unsigned int s_maxAutoNodeSize = 16*1024;
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);
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);
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;
131 ByteQueue::ByteQueue(
size_t nodeSize)
132 : m_lazyString(NULL), m_lazyLength(0)
134 SetNodeSize(nodeSize);
138 void ByteQueue::SetNodeSize(
size_t nodeSize)
140 m_autoNodeSize = !nodeSize;
141 m_nodeSize = m_autoNodeSize ? 256 : nodeSize;
144 ByteQueue::ByteQueue(
const ByteQueue ©)
150 void ByteQueue::CopyFrom(
const ByteQueue ©)
153 m_autoNodeSize = copy.m_autoNodeSize;
154 m_nodeSize = copy.m_nodeSize;
157 for (
ByteQueueNode *current=copy.m_head->next; current; current=current->next)
160 m_tail = m_tail->next;
165 Put(copy.m_lazyString, copy.m_lazyLength);
168 ByteQueue::~ByteQueue()
173 void ByteQueue::Destroy()
175 for (
ByteQueueNode *next, *current=m_head; current; current=next)
182 void ByteQueue::IsolatedInitialize(
const NameValuePairs ¶meters)
188 lword ByteQueue::CurrentSize()
const
192 for (
ByteQueueNode *current=m_head; current; current=current->next)
193 size += current->CurrentSize();
195 return size + m_lazyLength;
198 bool ByteQueue::IsEmpty()
const
200 return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0;
203 void ByteQueue::Clear()
205 for (
ByteQueueNode *next, *current=m_head->next; current; current=next)
217 size_t ByteQueue::Put2(
const byte *inString,
size_t length,
int messageEnd,
bool blocking)
219 if (m_lazyLength > 0)
223 while ((len=m_tail->Put(inString, length)) < length)
227 if (m_autoNodeSize && m_nodeSize < s_maxAutoNodeSize)
232 while (m_nodeSize < length && m_nodeSize < s_maxAutoNodeSize);
233 m_tail->next =
new ByteQueueNode(STDMAX(m_nodeSize, length));
234 m_tail = m_tail->next;
240 void ByteQueue::CleanupUsedNodes()
242 while (m_head != m_tail && m_head->UsedUp())
249 if (m_head->CurrentSize() == 0)
253 void ByteQueue::LazyPut(
const byte *inString,
size_t size)
255 if (m_lazyLength > 0)
258 if (inString == m_tail->buf+m_tail->m_tail)
262 m_lazyString =
const_cast<byte *
>(inString);
264 m_lazyStringModifiable =
false;
268 void ByteQueue::LazyPutModifiable(byte *inString,
size_t size)
270 if (m_lazyLength > 0)
272 m_lazyString = inString;
274 m_lazyStringModifiable =
true;
277 void ByteQueue::UndoLazyPut(
size_t size)
279 if (m_lazyLength < size)
280 throw InvalidArgument(
"ByteQueue: size specified for UndoLazyPut is too large");
282 m_lazyLength -= size;
285 void ByteQueue::FinalizeLazyPut()
287 size_t len = m_lazyLength;
290 Put(m_lazyString, len);
295 if (m_head->Get(outByte))
297 if (m_head->UsedUp())
301 else if (m_lazyLength > 0)
303 outByte = *m_lazyString++;
319 if (m_head->Peek(outByte))
321 else if (m_lazyLength > 0)
323 outByte = *m_lazyString;
333 return (
size_t)
CopyTo(sink, peekMax);
340 lword bytesLeft = transferBytes;
341 for (
ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
342 bytesLeft -= current->TransferTo(target, bytesLeft, channel);
345 size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
348 if (m_lazyStringModifiable)
349 target.ChannelPutModifiable(channel, m_lazyString, len);
351 target.ChannelPut(channel, m_lazyString, len);
356 transferBytes -= bytesLeft;
362 size_t blockedBytes = walker.
TransferTo2(target, transferBytes, channel, blocking);
372 lword transferBytes = end-begin;
373 size_t blockedBytes = walker.
TransferTo2(target, transferBytes, channel, blocking);
374 begin += transferBytes;
378 void ByteQueue::Unget(byte inByte)
383 void ByteQueue::Unget(
const byte *inString,
size_t length)
385 size_t len = STDMIN(length, m_head->m_head);
387 m_head->m_head -= len;
388 memcpy(m_head->buf + m_head->m_head, inString + length, len);
393 newHead->next = m_head;
395 m_head->Put(inString, length);
399 const byte * ByteQueue::Spy(
size_t &contiguousSize)
const
401 contiguousSize = m_head->m_tail - m_head->m_head;
402 if (contiguousSize == 0 && m_lazyLength > 0)
404 contiguousSize = m_lazyLength;
408 return m_head->buf + m_head->m_head;
413 if (m_lazyLength > 0)
416 if (m_tail->m_tail == m_tail->MaxSize())
419 m_tail = m_tail->next;
422 size = m_tail->MaxSize() - m_tail->m_tail;
423 return m_tail->buf + m_tail->m_tail;
433 bool ByteQueue::operator==(
const ByteQueue &rhs)
const
435 const lword currentSize = CurrentSize();
437 if (currentSize != rhs.CurrentSize())
440 Walker walker1(*
this), walker2(rhs);
443 while (walker1.Get(b1) && walker2.Get(b2))
450 byte ByteQueue::operator[](lword i)
const
452 for (
ByteQueueNode *current=m_head; current; current=current->next)
454 if (i < current->CurrentSize())
455 return (*current)[(size_t)i];
457 i -= current->CurrentSize();
460 assert(i < m_lazyLength);
461 return m_lazyString[i];
466 std::swap(m_autoNodeSize, rhs.m_autoNodeSize);
467 std::swap(m_nodeSize, rhs.m_nodeSize);
468 std::swap(m_head, rhs.m_head);
469 std::swap(m_tail, rhs.m_tail);
470 std::swap(m_lazyString, rhs.m_lazyString);
471 std::swap(m_lazyLength, rhs.m_lazyLength);
472 std::swap(m_lazyStringModifiable, rhs.m_lazyStringModifiable);
477 void ByteQueue::Walker::IsolatedInitialize(
const NameValuePairs ¶meters)
479 m_node = m_queue.m_head;
482 m_lazyString = m_queue.m_lazyString;
483 m_lazyLength = m_queue.m_lazyLength;
501 return (
size_t)
CopyTo(sink, 1);
507 return (
size_t)
CopyTo(sink, peekMax);
512 lword bytesLeft = transferBytes;
513 size_t blockedBytes = 0;
517 size_t len = (size_t)STDMIN(bytesLeft, (lword)m_node->CurrentSize()-m_offset);
518 blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking);
532 m_node = m_node->next;
536 if (bytesLeft && m_lazyLength)
538 size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
539 blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking);
549 transferBytes -= bytesLeft;
557 lword transferBytes = end-begin;
558 size_t blockedBytes = walker.
TransferTo2(target, transferBytes, channel, blocking);
559 begin += transferBytes;