summaryrefslogtreecommitdiffstats
path: root/botan/src/filters/secqueue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'botan/src/filters/secqueue.cpp')
-rw-r--r--botan/src/filters/secqueue.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/botan/src/filters/secqueue.cpp b/botan/src/filters/secqueue.cpp
new file mode 100644
index 0000000..f63ef89
--- /dev/null
+++ b/botan/src/filters/secqueue.cpp
@@ -0,0 +1,205 @@
+/*
+* SecureQueue
+* (C) 1999-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/secqueue.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*
+* SecureQueueNode
+*/
+class SecureQueueNode
+ {
+ public:
+ u32bit write(const byte input[], u32bit length)
+ {
+ u32bit copied = std::min(length, buffer.size() - end);
+ copy_mem(buffer + end, input, copied);
+ end += copied;
+ return copied;
+ }
+ u32bit read(byte output[], u32bit length)
+ {
+ u32bit copied = std::min(length, end - start);
+ copy_mem(output, buffer + start, copied);
+ start += copied;
+ return copied;
+ }
+ u32bit peek(byte output[], u32bit length, u32bit offset = 0)
+ {
+ const u32bit left = end - start;
+ if(offset >= left) return 0;
+ u32bit copied = std::min(length, left - offset);
+ copy_mem(output, buffer + start + offset, copied);
+ return copied;
+ }
+ u32bit size() const { return (end - start); }
+ SecureQueueNode() { next = 0; start = end = 0; }
+ ~SecureQueueNode() { next = 0; start = end = 0; }
+ private:
+ friend class SecureQueue;
+ SecureQueueNode* next;
+ SecureBuffer<byte, DEFAULT_BUFFERSIZE> buffer;
+ u32bit start, end;
+ };
+
+/*
+* Create a SecureQueue
+*/
+SecureQueue::SecureQueue()
+ {
+ set_next(0, 0);
+ head = tail = new SecureQueueNode;
+ }
+
+/*
+* Copy a SecureQueue
+*/
+SecureQueue::SecureQueue(const SecureQueue& input) :
+ Fanout_Filter(), DataSource()
+ {
+ set_next(0, 0);
+
+ head = tail = new SecureQueueNode;
+ SecureQueueNode* temp = input.head;
+ while(temp)
+ {
+ write(temp->buffer + temp->start, temp->end - temp->start);
+ temp = temp->next;
+ }
+ }
+
+/*
+* Destroy this SecureQueue
+*/
+void SecureQueue::destroy()
+ {
+ SecureQueueNode* temp = head;
+ while(temp)
+ {
+ SecureQueueNode* holder = temp->next;
+ delete temp;
+ temp = holder;
+ }
+ head = tail = 0;
+ }
+
+/*
+* Copy a SecureQueue
+*/
+SecureQueue& SecureQueue::operator=(const SecureQueue& input)
+ {
+ destroy();
+ head = tail = new SecureQueueNode;
+ SecureQueueNode* temp = input.head;
+ while(temp)
+ {
+ write(temp->buffer + temp->start, temp->end - temp->start);
+ temp = temp->next;
+ }
+ return (*this);
+ }
+
+/*
+* Add some bytes to the queue
+*/
+void SecureQueue::write(const byte input[], u32bit length)
+ {
+ if(!head)
+ head = tail = new SecureQueueNode;
+ while(length)
+ {
+ const u32bit n = tail->write(input, length);
+ input += n;
+ length -= n;
+ if(length)
+ {
+ tail->next = new SecureQueueNode;
+ tail = tail->next;
+ }
+ }
+ }
+
+/*
+* Read some bytes from the queue
+*/
+u32bit SecureQueue::read(byte output[], u32bit length)
+ {
+ u32bit got = 0;
+ while(length && head)
+ {
+ const u32bit n = head->read(output, length);
+ output += n;
+ got += n;
+ length -= n;
+ if(head->size() == 0)
+ {
+ SecureQueueNode* holder = head->next;
+ delete head;
+ head = holder;
+ }
+ }
+ return got;
+ }
+
+/*
+* Read data, but do not remove it from queue
+*/
+u32bit SecureQueue::peek(byte output[], u32bit length, u32bit offset) const
+ {
+ SecureQueueNode* current = head;
+
+ while(offset && current)
+ {
+ if(offset >= current->size())
+ {
+ offset -= current->size();
+ current = current->next;
+ }
+ else
+ break;
+ }
+
+ u32bit got = 0;
+ while(length && current)
+ {
+ const u32bit n = current->peek(output, length, offset);
+ offset = 0;
+ output += n;
+ got += n;
+ length -= n;
+ current = current->next;
+ }
+ return got;
+ }
+
+/*
+* Return how many bytes the queue holds
+*/
+u32bit SecureQueue::size() const
+ {
+ SecureQueueNode* current = head;
+ u32bit count = 0;
+
+ while(current)
+ {
+ count += current->size();
+ current = current->next;
+ }
+ return count;
+ }
+
+/*
+* Test if the queue has any data in it
+*/
+bool SecureQueue::end_of_data() const
+ {
+ return (size() == 0);
+ }
+
+}