Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

queue.cpp

00001 // queue.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "queue.h"
00005 #include "filters.h"
00006 
00007 NAMESPACE_BEGIN(CryptoPP)
00008 
00009 // this class for use by ByteQueue only
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         inline unsigned int Put(byte inByte)
00038         {
00039                 if (MaxSize()==m_tail)
00040                         return 0;
00041 
00042                 buf[m_tail++]=inByte;
00043                 return 1;
00044         }
00045 
00046         inline unsigned int Put(const byte *inString, unsigned int length)
00047         {
00048                 unsigned int l = STDMIN(length, MaxSize()-m_tail);
00049                 memcpy(buf+m_tail, inString, 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
00071         {
00072                 unsigned int len = m_tail-m_head;
00073                 target.Put(buf+m_head, len);
00074                 return len;
00075         }
00076 
00077         inline unsigned int CopyTo(BufferedTransformation &target, unsigned int copyMax) const
00078         {
00079                 unsigned int len = STDMIN(copyMax, m_tail-m_head);
00080                 target.Put(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)
00099         {
00100                 unsigned int len = CopyTo(target);
00101                 m_head += len;
00102                 return len;
00103         }
00104 
00105         inline unsigned int TransferTo(BufferedTransformation &target, unsigned int transferMax)
00106         {
00107                 unsigned int len = CopyTo(target, transferMax);
00108                 m_head += len;
00109                 return len;
00110         }
00111 
00112         inline unsigned int Skip(unsigned int skipMax)
00113         {
00114                 unsigned int len = STDMIN(skipMax, m_tail-m_head);
00115                 m_head += len;
00116                 return len;
00117         }
00118 
00119         inline byte operator[](unsigned int i) const
00120         {
00121                 return buf[m_head+i];
00122         }
00123 
00124         ByteQueueNode *next;
00125 
00126         SecByteBlock buf;
00127         unsigned int m_head, m_tail;
00128 };
00129 
00130 // ********************************************************
00131 
00132 ByteQueue::ByteQueue(unsigned int m_nodeSize)
00133         : m_nodeSize(m_nodeSize), m_lazyLength(0)
00134 {
00135         m_head = m_tail = new ByteQueueNode(m_nodeSize);
00136 }
00137 
00138 ByteQueue::ByteQueue(const ByteQueue &copy)
00139 {
00140         CopyFrom(copy);
00141 }
00142 
00143 void ByteQueue::CopyFrom(const ByteQueue &copy)
00144 {
00145         m_lazyLength = 0;
00146         m_nodeSize = copy.m_nodeSize;
00147         m_head = m_tail = new ByteQueueNode(*copy.m_head);
00148 
00149         for (ByteQueueNode *current=copy.m_head->next; current; current=current->next)
00150         {
00151                 m_tail->next = new ByteQueueNode(*current);
00152                 m_tail = m_tail->next;
00153         }
00154 
00155         m_tail->next = NULL;
00156 
00157         Put(copy.m_lazyString, copy.m_lazyLength);
00158 }
00159 
00160 ByteQueue::~ByteQueue()
00161 {
00162         Destroy();
00163 }
00164 
00165 void ByteQueue::Destroy()
00166 {
00167         ByteQueueNode *next;
00168 
00169         for (ByteQueueNode *current=m_head; current; current=next)
00170         {
00171                 next=current->next;
00172                 delete current;
00173         }
00174 }
00175 
00176 unsigned long ByteQueue::CurrentSize() const
00177 {
00178         unsigned long size=0;
00179 
00180         for (ByteQueueNode *current=m_head; current; current=current->next)
00181                 size += current->CurrentSize();
00182 
00183         return size + m_lazyLength;
00184 }
00185 
00186 bool ByteQueue::IsEmpty() const
00187 {
00188         return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0;
00189 }
00190 
00191 void ByteQueue::Clear()
00192 {
00193         Destroy();
00194         m_head = m_tail = new ByteQueueNode(m_nodeSize);
00195         m_lazyLength = 0;
00196 }
00197 
00198 void ByteQueue::Put(byte inByte)
00199 {
00200         if (m_lazyLength > 0)
00201                 FinalizeLazyPut();
00202 
00203         if (!m_tail->Put(inByte))
00204         {
00205                 m_tail->next = new ByteQueueNode(m_nodeSize);
00206                 m_tail = m_tail->next;
00207                 m_tail->Put(inByte);
00208         }
00209 }
00210 
00211 void ByteQueue::Put(const byte *inString, unsigned int length)
00212 {
00213         if (m_lazyLength > 0)
00214                 FinalizeLazyPut();
00215 
00216         unsigned int len;
00217         while ((len=m_tail->Put(inString, length)) < length)
00218         {
00219                 m_tail->next = new ByteQueueNode(m_nodeSize);
00220                 m_tail = m_tail->next;
00221                 inString += len;
00222                 length -= len;
00223         }
00224 }
00225 
00226 void ByteQueue::CleanupUsedNodes()
00227 {
00228         while (m_head != m_tail && m_head->UsedUp())
00229         {
00230                 ByteQueueNode *temp=m_head;
00231                 m_head=m_head->next;
00232                 delete temp;
00233         }
00234 
00235         if (m_head->CurrentSize() == 0)
00236                 m_head->Clear();
00237 }
00238 
00239 void ByteQueue::LazyPut(const byte *inString, unsigned int size)
00240 {
00241         if (m_lazyLength > 0)
00242                 FinalizeLazyPut();
00243         m_lazyString = inString;
00244         m_lazyLength = size;
00245 }
00246 
00247 void ByteQueue::FinalizeLazyPut()
00248 {
00249         unsigned int len = m_lazyLength;
00250         m_lazyLength = 0;
00251         Put(m_lazyString, len);
00252 }
00253 
00254 unsigned int ByteQueue::Get(byte &outByte)
00255 {
00256         if (m_head->Get(outByte))
00257         {
00258                 if (m_head->UsedUp())
00259                         CleanupUsedNodes();
00260                 return 1;
00261         }
00262         else if (m_lazyLength > 0)
00263         {
00264                 outByte = *m_lazyString++;
00265                 m_lazyLength--;
00266                 return 1;
00267         }
00268         else
00269                 return 0;
00270 }
00271 
00272 unsigned int ByteQueue::Get(byte *outString, unsigned int getMax)
00273 {
00274         ArraySink sink(outString, getMax);
00275         return TransferTo(sink, getMax);
00276 }
00277 
00278 unsigned int ByteQueue::Peek(byte &outByte) const
00279 {
00280         if (m_head->Peek(outByte))
00281                 return 1;
00282         else if (m_lazyLength > 0)
00283         {
00284                 outByte = *m_lazyString;
00285                 return 1;
00286         }
00287         else
00288                 return 0;
00289 }
00290 
00291 unsigned int ByteQueue::Peek(byte *outString, unsigned int peekMax) const
00292 {
00293         ArraySink sink(outString, peekMax);
00294         return CopyTo(sink, peekMax);
00295 }
00296 
00297 unsigned long ByteQueue::Skip(unsigned long skipMax)
00298 {
00299         return TransferTo(g_bitBucket, skipMax);
00300 }
00301 
00302 unsigned long ByteQueue::TransferTo(BufferedTransformation &target, unsigned long transferMax)
00303 {
00304         unsigned long bytesLeft = transferMax;
00305         for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
00306                 bytesLeft -= current->TransferTo(target, bytesLeft);
00307         CleanupUsedNodes();
00308 
00309         unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
00310         if (len)
00311         {
00312                 target.Put(m_lazyString, len);
00313                 m_lazyString += len;
00314                 m_lazyLength -= len;
00315                 bytesLeft -= len;
00316         }
00317         return transferMax - bytesLeft;
00318 }
00319 
00320 unsigned long ByteQueue::CopyTo(BufferedTransformation &target, unsigned long copyMax) const
00321 {
00322         unsigned long bytesLeft = copyMax;
00323         for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
00324                 bytesLeft -= current->CopyTo(target, bytesLeft);
00325         if (bytesLeft && m_lazyLength)
00326         {
00327                 unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
00328                 target.Put(m_lazyString, len);
00329                 bytesLeft -= len;
00330         }
00331         return copyMax - bytesLeft;
00332 }
00333 
00334 void ByteQueue::Unget(byte inByte)
00335 {
00336         Unget(&inByte, 1);
00337 }
00338 
00339 void ByteQueue::Unget(const byte *inString, unsigned int length)
00340 {
00341         ByteQueueNode *newHead = new ByteQueueNode(length);
00342         newHead->next = m_head;
00343         m_head = newHead;
00344         m_head->Put(inString, length);
00345 }
00346 /*
00347 byte * ByteQueue::Spy(unsigned int &contiguousSize)
00348 {
00349         contiguousSize = m_head->m_tail - m_head->m_head;
00350         return m_head->buf + m_head->m_head;
00351 }
00352 */
00353 const byte * ByteQueue::Spy(unsigned int &contiguousSize) const
00354 {
00355         contiguousSize = m_head->m_tail - m_head->m_head;
00356         if (contiguousSize == 0 && m_lazyLength > 0)
00357         {
00358                 contiguousSize = m_lazyLength;
00359                 return m_lazyString;
00360         }
00361         else
00362                 return m_head->buf + m_head->m_head;
00363 }
00364 
00365 byte * ByteQueue::MakeNewSpace(unsigned int &contiguousSize)
00366 {
00367         if (m_lazyLength > 0)
00368                 FinalizeLazyPut();
00369 
00370         if (m_tail->m_tail == m_tail->MaxSize())
00371         {
00372                 m_tail->next = new ByteQueueNode(m_nodeSize);
00373                 m_tail = m_tail->next;
00374         }
00375 
00376         contiguousSize = m_tail->MaxSize() - m_tail->m_tail;
00377         return m_tail->buf + m_tail->m_tail;
00378 }
00379 
00380 void ByteQueue::OccupyNewSpace(unsigned int size)
00381 {
00382         m_tail->m_tail += size;
00383         assert(m_tail->m_tail <= m_tail->MaxSize());
00384 }
00385 
00386 ByteQueue & ByteQueue::operator=(const ByteQueue &rhs)
00387 {
00388         Destroy();
00389         CopyFrom(rhs);
00390         return *this;
00391 }
00392 
00393 bool ByteQueue::operator==(const ByteQueue &rhs) const
00394 {
00395         const unsigned long currentSize = CurrentSize();
00396 
00397         if (currentSize != rhs.CurrentSize())
00398                 return false;
00399 
00400         Walker walker1(*this), walker2(rhs);
00401         byte b1, b2;
00402 
00403         while (walker1.Get(b1) && walker2.Get(b2))
00404                 if (b1 != b2)
00405                         return false;
00406 
00407         return true;
00408 }
00409 
00410 byte ByteQueue::operator[](unsigned long i) const
00411 {
00412         for (ByteQueueNode *current=m_head; current; current=current->next)
00413         {
00414                 if (i < current->CurrentSize())
00415                         return (*current)[i];
00416                 
00417                 i -= current->CurrentSize();
00418         }
00419 
00420         assert(i < m_lazyLength);
00421         return m_lazyString[i];
00422 }
00423 
00424 void ByteQueue::swap(ByteQueue &rhs)
00425 {
00426         std::swap(m_nodeSize, rhs.m_nodeSize);
00427         std::swap(m_head, rhs.m_head);
00428         std::swap(m_tail, rhs.m_tail);
00429         std::swap(m_lazyString, rhs.m_lazyString);
00430         std::swap(m_lazyLength, rhs.m_lazyLength);
00431 }
00432 
00433 // ********************************************************
00434 
00435 unsigned int ByteQueue::Walker::Get(byte &outByte)
00436 {
00437         ArraySink sink(&outByte, 1);
00438         return TransferTo(sink, 1);
00439 }
00440 
00441 unsigned int ByteQueue::Walker::Get(byte *outString, unsigned int getMax)
00442 {
00443         ArraySink sink(outString, getMax);
00444         return TransferTo(sink, getMax);
00445 }
00446 
00447 unsigned int ByteQueue::Walker::Peek(byte &outByte) const
00448 {
00449         ArraySink sink(&outByte, 1);
00450         return CopyTo(sink, 1);
00451 }
00452 
00453 unsigned int ByteQueue::Walker::Peek(byte *outString, unsigned int peekMax) const
00454 {
00455         ArraySink sink(outString, peekMax);
00456         return CopyTo(sink, peekMax);
00457 }
00458 
00459 unsigned long ByteQueue::Walker::TransferTo(BufferedTransformation &target, unsigned long transferMax)
00460 {
00461         unsigned long bytesLeft = transferMax;
00462         while (m_node)
00463         {
00464                 unsigned int len = STDMIN(bytesLeft, (unsigned long)m_node->CurrentSize()-m_offset);
00465                 target.Put(m_node->buf+m_node->m_head+m_offset, len);
00466                 m_position += len;
00467                 bytesLeft -= len;
00468 
00469                 if (!bytesLeft)
00470                 {
00471                         m_offset += len;
00472                         break;
00473                 }
00474 
00475                 m_node = m_node->next;
00476                 m_offset = 0;
00477         }
00478 
00479         unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
00480         if (len)
00481         {
00482                 target.Put(m_lazyString, len);
00483                 m_lazyString += len;
00484                 m_lazyLength -= len;
00485                 bytesLeft -= len;
00486         }
00487         return transferMax - bytesLeft;
00488 }
00489 
00490 unsigned long ByteQueue::Walker::Skip(unsigned long skipMax)
00491 {
00492         return TransferTo(g_bitBucket, skipMax);
00493 }
00494 
00495 unsigned long ByteQueue::Walker::CopyTo(BufferedTransformation &target, unsigned long copyMax) const
00496 {
00497         return Walker(*this).TransferTo(target, copyMax);
00498 }
00499 
00500 NAMESPACE_END

Generated at Mon Jan 15 01:16:35 2001 for Crypto++ by doxygen1.2.4 written by Dimitri van Heesch, © 1997-2000