267 lines
5.4 KiB
C++
267 lines
5.4 KiB
C++
// queue.cpp - written and placed in the public domain by Wei Dai
|
|
|
|
#include "pch.h"
|
|
#include "queue.h"
|
|
#include "misc.h"
|
|
|
|
// this class for use by ByteQueue only
|
|
class ByteQueueNode
|
|
{
|
|
public:
|
|
ByteQueueNode(unsigned int maxSize);
|
|
|
|
unsigned int CurrentSize() const
|
|
{return tail-head;}
|
|
unsigned int UsedUp() const
|
|
{return (head==MaxSize());}
|
|
|
|
unsigned int Put(byte inByte);
|
|
unsigned int Put(const byte *inString, unsigned int length);
|
|
|
|
unsigned int Get(byte &outByte);
|
|
unsigned int Get(byte *outString, unsigned int getMax);
|
|
|
|
unsigned int Peek(byte &outByte) const;
|
|
|
|
void CopyTo(BufferedTransformation &target) const
|
|
{target.Put(buf+head, tail-head);}
|
|
void CopyTo(byte *target) const
|
|
{memcpy(target, buf+head, tail-head);}
|
|
|
|
byte operator[](unsigned int i) const
|
|
{return buf[i-head];}
|
|
|
|
ByteQueueNode *next;
|
|
|
|
private:
|
|
unsigned int MaxSize() const {return buf.size;}
|
|
|
|
SecByteBlock buf;
|
|
unsigned int head, tail;
|
|
};
|
|
|
|
|
|
ByteQueueNode::ByteQueueNode(unsigned int maxSize)
|
|
: buf(maxSize)
|
|
{
|
|
head = tail = 0;
|
|
next = 0;
|
|
}
|
|
|
|
unsigned int ByteQueueNode::Put(byte inByte)
|
|
{
|
|
if (MaxSize()==tail)
|
|
return 0;
|
|
|
|
buf[tail++]=inByte;
|
|
return 1;
|
|
}
|
|
|
|
unsigned int ByteQueueNode::Put(const byte *inString, unsigned int length)
|
|
{
|
|
unsigned int l = STDMIN(length, MaxSize()-tail);
|
|
memcpy(buf+tail, inString, l);
|
|
tail += l;
|
|
return l;
|
|
}
|
|
|
|
unsigned int ByteQueueNode::Get(byte &outByte)
|
|
{
|
|
if (tail==head)
|
|
return 0;
|
|
|
|
outByte=buf[head++];
|
|
return 1;
|
|
}
|
|
|
|
unsigned int ByteQueueNode::Get(byte *outString, unsigned int getMax)
|
|
{
|
|
unsigned int l = STDMIN(getMax, tail-head);
|
|
memcpy(outString, buf+head, l);
|
|
head += l;
|
|
return l;
|
|
}
|
|
|
|
unsigned int ByteQueueNode::Peek(byte &outByte) const
|
|
{
|
|
if (tail==head)
|
|
return 0;
|
|
|
|
outByte=buf[head];
|
|
return 1;
|
|
}
|
|
|
|
// ********************************************************
|
|
|
|
ByteQueue::ByteQueue(unsigned int nodeSize)
|
|
: nodeSize(nodeSize)
|
|
{
|
|
head = tail = new ByteQueueNode(nodeSize);
|
|
}
|
|
|
|
ByteQueue::ByteQueue(const ByteQueue ©)
|
|
{
|
|
CopyFrom(copy);
|
|
}
|
|
|
|
void ByteQueue::CopyFrom(const ByteQueue ©)
|
|
{
|
|
nodeSize = copy.nodeSize;
|
|
head = tail = new ByteQueueNode(*copy.head);
|
|
|
|
for (ByteQueueNode *current=copy.head->next; current; current=current->next)
|
|
{
|
|
tail->next = new ByteQueueNode(*current);
|
|
tail = tail->next;
|
|
}
|
|
|
|
tail->next = NULL;
|
|
}
|
|
|
|
ByteQueue::~ByteQueue()
|
|
{
|
|
Destroy();
|
|
}
|
|
|
|
void ByteQueue::Destroy()
|
|
{
|
|
ByteQueueNode *next;
|
|
|
|
for (ByteQueueNode *current=head; current; current=next)
|
|
{
|
|
next=current->next;
|
|
delete current;
|
|
}
|
|
}
|
|
|
|
void ByteQueue::CopyTo(BufferedTransformation &target) const
|
|
{
|
|
for (ByteQueueNode *current=head; current; current=current->next)
|
|
current->CopyTo(target);
|
|
}
|
|
|
|
void ByteQueue::CopyTo(byte *target) const
|
|
{
|
|
for (ByteQueueNode *current=head; current; current=current->next)
|
|
{
|
|
current->CopyTo(target);
|
|
target += current->CurrentSize();
|
|
}
|
|
}
|
|
|
|
unsigned long ByteQueue::CurrentSize() const
|
|
{
|
|
unsigned long size=0;
|
|
|
|
for (ByteQueueNode *current=head; current; current=current->next)
|
|
size += current->CurrentSize();
|
|
|
|
return size;
|
|
}
|
|
|
|
void ByteQueue::Put(byte inByte)
|
|
{
|
|
if (!tail->Put(inByte))
|
|
{
|
|
tail->next = new ByteQueueNode(nodeSize);
|
|
tail = tail->next;
|
|
tail->Put(inByte);
|
|
}
|
|
}
|
|
|
|
void ByteQueue::Put(const byte *inString, unsigned int length)
|
|
{
|
|
unsigned int l;
|
|
|
|
while ((l=tail->Put(inString, length)) < length)
|
|
{
|
|
tail->next = new ByteQueueNode(nodeSize);
|
|
tail = tail->next;
|
|
inString += l;
|
|
length -= l;
|
|
}
|
|
}
|
|
|
|
unsigned int ByteQueue::Get(byte &outByte)
|
|
{
|
|
int l = head->Get(outByte);
|
|
if (head->UsedUp())
|
|
{
|
|
ByteQueueNode *temp=head;
|
|
head = head->next;
|
|
delete temp;
|
|
if (!head) // just deleted the last node
|
|
head = tail = new ByteQueueNode(nodeSize);
|
|
}
|
|
return l;
|
|
}
|
|
|
|
unsigned int ByteQueue::Get(byte *outString, unsigned int getMax)
|
|
{
|
|
unsigned int getMaxSave=getMax;
|
|
ByteQueueNode *current=head;
|
|
|
|
while (getMax && current)
|
|
{
|
|
int l=current->Get(outString, getMax);
|
|
|
|
outString += l;
|
|
getMax -= l;
|
|
|
|
current = current->next;
|
|
}
|
|
|
|
while (head && head->UsedUp())
|
|
{
|
|
current=head;
|
|
head=head->next;
|
|
delete current;
|
|
}
|
|
|
|
if (!head) // every single node has been used up and deleted
|
|
head = tail = new ByteQueueNode(nodeSize);
|
|
|
|
return (getMaxSave-getMax);
|
|
}
|
|
|
|
unsigned int ByteQueue::Peek(byte &outByte) const
|
|
{
|
|
return head->Peek(outByte);
|
|
}
|
|
|
|
ByteQueue & ByteQueue::operator=(const ByteQueue &rhs)
|
|
{
|
|
Destroy();
|
|
CopyFrom(rhs);
|
|
return *this;
|
|
}
|
|
|
|
bool ByteQueue::operator==(const ByteQueue &rhs) const
|
|
{
|
|
const unsigned long currentSize = CurrentSize();
|
|
|
|
if (currentSize != rhs.CurrentSize())
|
|
return false;
|
|
|
|
for (unsigned long i = 0; i<currentSize; i++)
|
|
if ((*this)[i] != rhs[i])
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
byte ByteQueue::operator[](unsigned long i) const
|
|
{
|
|
for (ByteQueueNode *current=head; current; current=current->next)
|
|
{
|
|
if (i < current->CurrentSize())
|
|
return (*current)[i];
|
|
|
|
i -= current->CurrentSize();
|
|
}
|
|
|
|
// i should be less than CurrentSize(), therefore we should not be here
|
|
assert(false);
|
|
return 0;
|
|
}
|