aboutsummaryrefslogtreecommitdiffstats
path: root/src/libdash/source/helpers/BlockStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdash/source/helpers/BlockStream.cpp')
-rw-r--r--src/libdash/source/helpers/BlockStream.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/src/libdash/source/helpers/BlockStream.cpp b/src/libdash/source/helpers/BlockStream.cpp
new file mode 100644
index 00000000..fd34f88e
--- /dev/null
+++ b/src/libdash/source/helpers/BlockStream.cpp
@@ -0,0 +1,290 @@
+/*
+ * BlockStream.cpp
+ *****************************************************************************
+ * Copyright (C) 2012, bitmovin Softwareentwicklung OG, All Rights Reserved
+ *
+ * Email: libdash-dev@vicky.bitmovin.net
+ *
+ * This source code and its use and distribution, is subject to the terms
+ * and conditions of the applicable license agreement.
+ *****************************************************************************/
+
+#include "BlockStream.h"
+#include <limits>
+
+using namespace dash::helpers;
+
+BlockStream::BlockStream () :
+ length (0)
+{
+}
+BlockStream::~BlockStream ()
+{
+ this->Clear();
+}
+
+void BlockStream::PopAndDeleteFront ()
+{
+ if(this->blockqueue.empty())
+ return;
+
+ this->length -= this->blockqueue.front()->len;
+ DeleteBlock(this->blockqueue.front());
+ this->blockqueue.pop_front();
+}
+void BlockStream::PushBack (block_t *block)
+{
+ this->length += block->len;
+ this->blockqueue.push_back(block);
+}
+void BlockStream::PushFront (block_t *block)
+{
+ this->length += block->len;
+ this->blockqueue.push_front(block);
+}
+const block_t* BlockStream::GetBytes (uint32_t len)
+{
+ /* Performance Intensive */
+ if(this->length < len)
+ return NULL;
+
+ block_t *block = AllocBlock(len);
+ this->BlockQueueGetBytes(block->data, block->len);
+
+ this->length -= len;
+
+ return block;
+}
+size_t BlockStream::GetBytes (uint8_t *data, size_t len)
+{
+ /* Performance Intensive */
+ if(len > this->length)
+ len = (size_t) this->length;
+
+ this->BlockQueueGetBytes(data, len);
+
+ this->length -= len;
+
+ return len;
+}
+size_t BlockStream::PeekBytes (uint8_t *data, size_t len)
+{
+ /* Performance Intensive */
+ if(len > this->length)
+ len = (size_t) this->length;
+
+ this->BlockQueuePeekBytes(data, len, 0);
+
+ return len;
+}
+size_t BlockStream::PeekBytes (uint8_t *data, size_t len, size_t offset)
+{
+ /* Performance Intensive */
+ if(len > this->length)
+ len = (size_t) this->length;
+
+ if (offset + len > this->length)
+ len = (size_t) (this->length - offset);
+
+ this->BlockQueuePeekBytes(data, len, offset);
+
+ return len;
+}
+uint64_t BlockStream::Length () const
+{
+ return this->length;
+}
+const block_t* BlockStream::GetFront ()
+{
+ if(this->blockqueue.empty())
+ return NULL;
+
+ const block_t* ret = this->blockqueue.front();
+ this->length -= ret->len;
+ this->blockqueue.pop_front();
+
+ return ret;
+}
+const block_t* BlockStream::Front () const
+{
+ if(this->blockqueue.empty())
+ return NULL;
+
+ return this->blockqueue.front();
+}
+bool BlockStream::BlockQueueGetBytes (uint8_t *data, uint32_t len)
+{
+ uint32_t pos = 0;
+
+ block_t *block = NULL;
+
+ while(pos < len)
+ {
+ block = this->blockqueue.front();
+ if((len - pos) < (block->len))
+ {
+ memcpy(data + pos, block->data, len - pos);
+
+ this->blockqueue.pop_front();
+
+ block_t* newfront = AllocBlock(block->len - (len - pos));
+ memcpy(newfront->data, block->data + (len - pos), newfront->len);
+
+ DeleteBlock(block);
+ this->blockqueue.push_front(newfront);
+
+ return true;
+ }
+ else
+ {
+ memcpy(data + pos, block->data, block->len);
+ pos += block->len;
+
+ DeleteBlock(block);
+ this->blockqueue.pop_front();
+ }
+ }
+
+ return false;
+}
+bool BlockStream::BlockQueuePeekBytes (uint8_t *data, uint32_t len, size_t offset)
+{
+ uint32_t pos = 0;
+ int cnt = 0;
+
+ const block_t *block = NULL;
+
+ while(pos < len)
+ {
+ block = this->blockqueue.at(cnt);
+ if((offset + len - pos) < (block->len))
+ {
+ memcpy(data + pos, block->data + offset, len - pos - offset);
+ return true;
+ }
+ else
+ {
+ memcpy(data + pos, block->data + offset, block->len - offset);
+ pos += block->len;
+ }
+
+ cnt++;
+ }
+
+ return false;
+}
+uint8_t BlockStream::ByteAt (uint64_t position) const
+{
+ if(position > this->length)
+ return -1;
+
+ uint64_t pos = 0;
+
+ for(size_t i = 0; i < this->blockqueue.size(); i++)
+ {
+ const block_t *block = this->blockqueue.at(i);
+
+ if(pos + block->len > position)
+ return block->data[position - pos];
+ else
+ pos += block->len;
+ }
+
+ return -1;
+}
+const block_t* BlockStream::ToBlock ()
+{
+ if(this->length > std::numeric_limits<size_t>::max())
+ return NULL;
+
+ return BlockStream::GetBytes((size_t)this->length);
+}
+void BlockStream::Clear ()
+{
+ while(!this->blockqueue.empty())
+ {
+ DeleteBlock(this->blockqueue.front());
+ this->blockqueue.pop_front();
+ }
+
+ this->length = 0;
+}
+void BlockStream::EraseFront (uint64_t len)
+{
+ if(len > this->length)
+ len = this->length;
+
+ uint64_t actLen = 0;
+
+ while(actLen < len)
+ {
+ if(this->blockqueue.size() == 0)
+ return;
+
+ block_t *front = this->blockqueue.front();
+
+ if((actLen + front->len) <= len)
+ {
+ this->length -= front->len;
+ actLen += front->len;
+
+ DeleteBlock(front);
+ this->blockqueue.pop_front();
+ }
+ else
+ {
+ uint32_t diff = (uint32_t) (len - actLen);
+ this->length -= diff;
+ actLen += diff;
+ block_t* newfront = AllocBlock(front->len - diff);
+
+ memcpy(newfront->data, front->data + diff, newfront->len);
+
+ DeleteBlock(front);
+ this->blockqueue.pop_front();
+ this->blockqueue.push_front(newfront);
+ }
+ }
+}
+BlockStream* BlockStream::GetBlocks (uint64_t len)
+{
+ if(len > this->length)
+ return NULL;
+
+ BlockStream *blocks = new BlockStream();
+
+ uint64_t actLen = 0;
+
+ while(actLen < len)
+ {
+ block_t *front = this->blockqueue.front();
+
+ if((actLen + front->len) <= len)
+ {
+ this->length -= front->len;
+ actLen += front->len;
+
+ blocks->PushBack(front);
+ this->blockqueue.pop_front();
+ }
+ else
+ {
+ uint32_t diff = (uint32_t) (len - actLen);
+ this->length -= diff;
+ actLen += diff;
+ block_t *block = AllocBlock(diff);
+ block_t* newfront = AllocBlock(front->len - diff);
+
+ memcpy(block->data, front->data, diff);
+ blocks->PushBack(block);
+
+ memcpy(newfront->data, front->data+ diff, newfront->len);
+
+ DeleteBlock(front);
+ this->blockqueue.pop_front();
+ this->blockqueue.push_front(newfront);
+ }
+ }
+
+ return blocks;
+}