00001
00002
00003
#include "pch.h"
00004
#include "queue.h"
00005
#include "filters.h"
00006
00007 NAMESPACE_BEGIN(CryptoPP)
00008
00009
00010 class ByteQueueNode
00011 {
00012
public:
00013 ByteQueueNode(
unsigned int maxSize)
00014 : buf(maxSize)
00015 {
00016 m_head = m_tail = 0;
00017 next = 0;
00018 }
00019
00020
inline unsigned int MaxSize()
const {
return buf.size();}
00021
00022
inline unsigned int CurrentSize()
const
00023
{
00024
return m_tail-m_head;
00025 }
00026
00027
inline bool UsedUp()
const
00028
{
00029
return (m_head==MaxSize());
00030 }
00031
00032
inline void Clear()
00033 {
00034 m_head = m_tail = 0;
00035 }
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
inline unsigned int Put(
const byte *begin,
unsigned int length)
00047 {
00048
unsigned int l = STDMIN(length, MaxSize()-m_tail);
00049 memcpy(buf+m_tail, begin, l);
00050 m_tail += l;
00051
return l;
00052 }
00053
00054
inline unsigned int Peek(byte &outByte)
const
00055
{
00056
if (m_tail==m_head)
00057
return 0;
00058
00059 outByte=buf[m_head];
00060
return 1;
00061 }
00062
00063
inline unsigned int Peek(byte *target,
unsigned int copyMax)
const
00064
{
00065
unsigned int len = STDMIN(copyMax, m_tail-m_head);
00066 memcpy(target, buf+m_head, len);
00067
return len;
00068 }
00069
00070
inline unsigned int CopyTo(
BufferedTransformation &target,
const std::string &channel=BufferedTransformation::NULL_CHANNEL)
const
00071
{
00072
unsigned int len = m_tail-m_head;
00073 target.
ChannelPut(channel, buf+m_head, len);
00074
return len;
00075 }
00076
00077
inline unsigned int CopyTo(
BufferedTransformation &target,
unsigned int copyMax,
const std::string &channel=BufferedTransformation::NULL_CHANNEL)
const
00078
{
00079
unsigned int len = STDMIN(copyMax, m_tail-m_head);
00080 target.
ChannelPut(channel, buf+m_head, len);
00081
return len;
00082 }
00083
00084
inline unsigned int Get(byte &outByte)
00085 {
00086
unsigned int len = Peek(outByte);
00087 m_head += len;
00088
return len;
00089 }
00090
00091
inline unsigned int Get(byte *outString,
unsigned int getMax)
00092 {
00093
unsigned int len = Peek(outString, getMax);
00094 m_head += len;
00095
return len;
00096 }
00097
00098
inline unsigned int TransferTo(
BufferedTransformation &target,
const std::string &channel=BufferedTransformation::NULL_CHANNEL)
00099 {
00100
unsigned int len = m_tail-m_head;
00101 target.
ChannelPutModifiable(channel, buf+m_head, len);
00102 m_head = m_tail;
00103
return len;
00104 }
00105
00106
inline unsigned int TransferTo(
BufferedTransformation &target,
unsigned int transferMax,
const std::string &channel=BufferedTransformation::NULL_CHANNEL)
00107 {
00108
unsigned int len = STDMIN(transferMax, m_tail-m_head);
00109 target.
ChannelPutModifiable(channel, buf+m_head, len);
00110 m_head += len;
00111
return len;
00112 }
00113
00114
inline unsigned int Skip(
unsigned int skipMax)
00115 {
00116
unsigned int len = STDMIN(skipMax, m_tail-m_head);
00117 m_head += len;
00118
return len;
00119 }
00120
00121
inline byte operator[](
unsigned int i)
const
00122
{
00123
return buf[m_head+i];
00124 }
00125
00126 ByteQueueNode *next;
00127
00128
SecByteBlock buf;
00129
unsigned int m_head, m_tail;
00130 };
00131
00132
00133
00134 ByteQueue::ByteQueue(
unsigned int m_nodeSize)
00135 : m_nodeSize(m_nodeSize), m_lazyLength(0)
00136 {
00137 m_head = m_tail =
new ByteQueueNode(m_nodeSize);
00138 }
00139
00140 ByteQueue::ByteQueue(
const ByteQueue ©)
00141 {
00142 CopyFrom(copy);
00143 }
00144
00145
void ByteQueue::CopyFrom(
const ByteQueue ©)
00146 {
00147 m_lazyLength = 0;
00148 m_nodeSize = copy.
m_nodeSize;
00149 m_head = m_tail =
new ByteQueueNode(*copy.
m_head);
00150
00151
for (ByteQueueNode *current=copy.
m_head->next; current; current=current->next)
00152 {
00153 m_tail->next =
new ByteQueueNode(*current);
00154 m_tail = m_tail->next;
00155 }
00156
00157 m_tail->next = NULL;
00158
00159 Put(copy.
m_lazyString, copy.
m_lazyLength);
00160 }
00161
00162 ByteQueue::~ByteQueue()
00163 {
00164 Destroy();
00165 }
00166
00167
void ByteQueue::Destroy()
00168 {
00169 ByteQueueNode *next;
00170
00171
for (ByteQueueNode *current=m_head; current; current=next)
00172 {
00173 next=current->next;
00174
delete current;
00175 }
00176 }
00177
00178
void ByteQueue::IsolatedInitialize(
const NameValuePairs ¶meters)
00179 {
00180 m_nodeSize = parameters.
GetIntValueWithDefault(
"NodeSize", 256);
00181 Clear();
00182 }
00183
00184
unsigned long ByteQueue::CurrentSize()
const
00185
{
00186
unsigned long size=0;
00187
00188
for (ByteQueueNode *current=m_head; current; current=current->next)
00189 size += current->CurrentSize();
00190
00191
return size + m_lazyLength;
00192 }
00193
00194
bool ByteQueue::IsEmpty()
const
00195
{
00196
return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0;
00197 }
00198
00199
void ByteQueue::Clear()
00200 {
00201 Destroy();
00202 m_head = m_tail =
new ByteQueueNode(m_nodeSize);
00203 m_lazyLength = 0;
00204 }
00205
00206
unsigned int ByteQueue::Put2(
const byte *inString,
unsigned int length,
int messageEnd,
bool blocking)
00207 {
00208
if (m_lazyLength > 0)
00209 FinalizeLazyPut();
00210
00211
unsigned int len;
00212
while ((len=m_tail->Put(inString, length)) < length)
00213 {
00214 m_tail->next =
new ByteQueueNode(m_nodeSize);
00215 m_tail = m_tail->next;
00216 inString += len;
00217 length -= len;
00218 }
00219
00220
return 0;
00221 }
00222
00223
void ByteQueue::CleanupUsedNodes()
00224 {
00225
while (m_head != m_tail && m_head->UsedUp())
00226 {
00227 ByteQueueNode *temp=m_head;
00228 m_head=m_head->next;
00229
delete temp;
00230 }
00231
00232
if (m_head->CurrentSize() == 0)
00233 m_head->Clear();
00234 }
00235
00236
void ByteQueue::LazyPut(
const byte *inString,
unsigned int size)
00237 {
00238
if (m_lazyLength > 0)
00239 FinalizeLazyPut();
00240 m_lazyString = inString;
00241 m_lazyLength = size;
00242 }
00243
00244
void ByteQueue::UndoLazyPut(
unsigned int size)
00245 {
00246
if (m_lazyLength < size)
00247
throw InvalidArgument(
"ByteQueue: size specified for UndoLazyPut is too large");
00248
00249 m_lazyLength -= size;
00250 }
00251
00252
void ByteQueue::FinalizeLazyPut()
00253 {
00254
unsigned int len = m_lazyLength;
00255 m_lazyLength = 0;
00256
if (len)
00257 Put(m_lazyString, len);
00258 }
00259
00260
unsigned int ByteQueue::Get(byte &outByte)
00261 {
00262
if (m_head->Get(outByte))
00263 {
00264
if (m_head->UsedUp())
00265 CleanupUsedNodes();
00266
return 1;
00267 }
00268
else if (m_lazyLength > 0)
00269 {
00270 outByte = *m_lazyString++;
00271 m_lazyLength--;
00272
return 1;
00273 }
00274
else
00275
return 0;
00276 }
00277
00278
unsigned int ByteQueue::Get(byte *outString,
unsigned int getMax)
00279 {
00280
ArraySink sink(outString, getMax);
00281
return TransferTo(sink, getMax);
00282 }
00283
00284
unsigned int ByteQueue::Peek(byte &outByte)
const
00285
{
00286
if (m_head->Peek(outByte))
00287
return 1;
00288
else if (m_lazyLength > 0)
00289 {
00290 outByte = *m_lazyString;
00291
return 1;
00292 }
00293
else
00294
return 0;
00295 }
00296
00297
unsigned int ByteQueue::Peek(byte *outString,
unsigned int peekMax)
const
00298
{
00299
ArraySink sink(outString, peekMax);
00300
return CopyTo(sink, peekMax);
00301 }
00302
00303
unsigned int ByteQueue::TransferTo2(
BufferedTransformation &target,
unsigned long &transferBytes,
const std::string &channel,
bool blocking)
00304 {
00305
if (blocking)
00306 {
00307
unsigned long bytesLeft = transferBytes;
00308
for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
00309 bytesLeft -= current->TransferTo(target, bytesLeft, channel);
00310 CleanupUsedNodes();
00311
00312
unsigned int len = (
unsigned int)STDMIN(bytesLeft, (
unsigned long)m_lazyLength);
00313
if (len)
00314 {
00315 target.
ChannelPut(channel, m_lazyString, len);
00316 m_lazyString += len;
00317 m_lazyLength -= len;
00318 bytesLeft -= len;
00319 }
00320 transferBytes -= bytesLeft;
00321
return 0;
00322 }
00323
else
00324 {
00325 Walker walker(*
this);
00326
unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
00327 Skip(transferBytes);
00328
return blockedBytes;
00329 }
00330 }
00331
00332
unsigned int ByteQueue::CopyRangeTo2(
BufferedTransformation &target,
unsigned long &begin,
unsigned long end,
const std::string &channel,
bool blocking)
const
00333
{
00334 Walker walker(*
this);
00335 walker.Skip(begin);
00336
unsigned long transferBytes = end-begin;
00337
unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
00338 begin += transferBytes;
00339
return blockedBytes;
00340 }
00341
00342
void ByteQueue::Unget(byte inByte)
00343 {
00344 Unget(&inByte, 1);
00345 }
00346
00347
void ByteQueue::Unget(
const byte *inString,
unsigned int length)
00348 {
00349
00350 ByteQueueNode *newHead =
new ByteQueueNode(length);
00351 newHead->next = m_head;
00352 m_head = newHead;
00353 m_head->Put(inString, length);
00354 }
00355
00356
const byte * ByteQueue::Spy(
unsigned int &contiguousSize)
const
00357
{
00358 contiguousSize = m_head->m_tail - m_head->m_head;
00359
if (contiguousSize == 0 && m_lazyLength > 0)
00360 {
00361 contiguousSize = m_lazyLength;
00362
return m_lazyString;
00363 }
00364
else
00365
return m_head->buf + m_head->m_head;
00366 }
00367
00368 byte * ByteQueue::CreatePutSpace(
unsigned int &size)
00369 {
00370
if (m_lazyLength > 0)
00371 FinalizeLazyPut();
00372
00373
if (m_tail->m_tail == m_tail->MaxSize())
00374 {
00375 m_tail->next =
new ByteQueueNode(size < m_nodeSize ? m_nodeSize : STDMAX(m_nodeSize, 1024U));
00376 m_tail = m_tail->next;
00377 }
00378
00379 size = m_tail->MaxSize() - m_tail->m_tail;
00380
return m_tail->buf + m_tail->m_tail;
00381 }
00382
00383
ByteQueue & ByteQueue::operator=(
const ByteQueue &rhs)
00384 {
00385 Destroy();
00386 CopyFrom(rhs);
00387
return *
this;
00388 }
00389
00390
bool ByteQueue::operator==(
const ByteQueue &rhs)
const
00391
{
00392
const unsigned long currentSize = CurrentSize();
00393
00394
if (currentSize != rhs.
CurrentSize())
00395
return false;
00396
00397 Walker walker1(*
this), walker2(rhs);
00398 byte b1, b2;
00399
00400
while (walker1.Get(b1) && walker2.Get(b2))
00401
if (b1 != b2)
00402
return false;
00403
00404
return true;
00405 }
00406
00407 byte ByteQueue::operator[](
unsigned long i)
const
00408
{
00409
for (ByteQueueNode *current=m_head; current; current=current->next)
00410 {
00411
if (i < current->CurrentSize())
00412
return (*current)[i];
00413
00414 i -= current->CurrentSize();
00415 }
00416
00417 assert(i < m_lazyLength);
00418
return m_lazyString[i];
00419 }
00420
00421
void ByteQueue::swap(
ByteQueue &rhs)
00422 {
00423 std::swap(m_nodeSize, rhs.
m_nodeSize);
00424 std::swap(m_head, rhs.
m_head);
00425 std::swap(m_tail, rhs.
m_tail);
00426 std::swap(m_lazyString, rhs.
m_lazyString);
00427 std::swap(m_lazyLength, rhs.
m_lazyLength);
00428 }
00429
00430
00431
00432
void ByteQueue::Walker::IsolatedInitialize(
const NameValuePairs ¶meters)
00433 {
00434 m_node = m_queue.m_head;
00435 m_position = 0;
00436 m_offset = 0;
00437 m_lazyString = m_queue.m_lazyString;
00438 m_lazyLength = m_queue.m_lazyLength;
00439 }
00440
00441
unsigned int ByteQueue::Walker::Get(byte &outByte)
00442 {
00443
ArraySink sink(&outByte, 1);
00444
return TransferTo(sink, 1);
00445 }
00446
00447
unsigned int ByteQueue::Walker::Get(byte *outString,
unsigned int getMax)
00448 {
00449
ArraySink sink(outString, getMax);
00450
return TransferTo(sink, getMax);
00451 }
00452
00453
unsigned int ByteQueue::Walker::Peek(byte &outByte)
const
00454
{
00455
ArraySink sink(&outByte, 1);
00456
return CopyTo(sink, 1);
00457 }
00458
00459
unsigned int ByteQueue::Walker::Peek(byte *outString,
unsigned int peekMax)
const
00460
{
00461
ArraySink sink(outString, peekMax);
00462
return CopyTo(sink, peekMax);
00463 }
00464
00465
unsigned int ByteQueue::Walker::TransferTo2(
BufferedTransformation &target,
unsigned long &transferBytes,
const std::string &channel,
bool blocking)
00466 {
00467
unsigned long bytesLeft = transferBytes;
00468
unsigned int blockedBytes = 0;
00469
00470
while (m_node)
00471 {
00472
unsigned int len = STDMIN(bytesLeft, (
unsigned long)m_node->CurrentSize()-m_offset);
00473 blockedBytes = target.
ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking);
00474
00475
if (blockedBytes)
00476
goto done;
00477
00478 m_position += len;
00479 bytesLeft -= len;
00480
00481
if (!bytesLeft)
00482 {
00483 m_offset += len;
00484
goto done;
00485 }
00486
00487 m_node = m_node->next;
00488 m_offset = 0;
00489 }
00490
00491
if (bytesLeft && m_lazyLength)
00492 {
00493
unsigned int len = (
unsigned int)STDMIN(bytesLeft, (
unsigned long)m_lazyLength);
00494
unsigned int blockedBytes = target.
ChannelPut2(channel, m_lazyString, len, 0, blocking);
00495
if (blockedBytes)
00496
goto done;
00497
00498 m_lazyString += len;
00499 m_lazyLength -= len;
00500 bytesLeft -= len;
00501 }
00502
00503 done:
00504 transferBytes -= bytesLeft;
00505
return blockedBytes;
00506 }
00507
00508
unsigned int ByteQueue::Walker::CopyRangeTo2(
BufferedTransformation &target,
unsigned long &begin,
unsigned long end,
const std::string &channel,
bool blocking)
const
00509
{
00510 Walker walker(*
this);
00511 walker.Skip(begin);
00512
unsigned long transferBytes = end-begin;
00513
unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
00514 begin += transferBytes;
00515
return blockedBytes;
00516 }
00517
00518 NAMESPACE_END