diff options
Diffstat (limited to 'botan/src/filters/secqueue.cpp')
-rw-r--r-- | botan/src/filters/secqueue.cpp | 205 |
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); + } + +} |