2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file binary_queue.cpp
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of binary queue
23 #include <dpl/binary_queue.h>
24 #include <dpl/assert.h>
25 #include <dpl/free_deleter.h>
33 BinaryQueue::BinaryQueue() :
37 BinaryQueue::BinaryQueue(const BinaryQueue &other) :
40 AppendCopyFrom(other);
43 BinaryQueue::~BinaryQueue()
45 // Remove all remainig buckets
49 BinaryQueue &BinaryQueue::operator=(const BinaryQueue &other)
53 AppendCopyFrom(other);
59 void BinaryQueue::AppendCopyFrom(const BinaryQueue &other)
61 // To speed things up, always copy as one bucket
62 void *bufferCopy = malloc(other.m_size);
64 if (bufferCopy == NULL) {
65 throw std::bad_alloc();
69 other.Flatten(bufferCopy, other.m_size);
70 AppendUnmanaged(bufferCopy, other.m_size, &BufferDeleterFree, NULL);
71 } catch (const std::bad_alloc &) {
72 // Free allocated memory
78 void BinaryQueue::AppendMoveFrom(BinaryQueue &other)
81 std::copy(other.m_buckets.begin(),
82 other.m_buckets.end(), std::back_inserter(m_buckets));
83 m_size += other.m_size;
85 // Clear other, but do not free memory
86 other.m_buckets.clear();
90 void BinaryQueue::AppendCopyTo(BinaryQueue &other) const
92 other.AppendCopyFrom(*this);
95 void BinaryQueue::AppendMoveTo(BinaryQueue &other)
97 other.AppendMoveFrom(*this);
100 void BinaryQueue::Clear()
102 std::for_each(m_buckets.begin(), m_buckets.end(), &DeleteBucket);
107 void BinaryQueue::AppendCopy(const void* buffer, size_t bufferSize)
109 // Create data copy with malloc/free
110 void *bufferCopy = malloc(bufferSize);
112 // Check if allocation succeded
113 if (bufferCopy == NULL) {
114 throw std::bad_alloc();
118 memcpy(bufferCopy, buffer, bufferSize);
121 // Try to append new bucket
122 AppendUnmanaged(bufferCopy, bufferSize, &BufferDeleterFree, NULL);
123 } catch (const std::bad_alloc &) {
124 // Free allocated memory
130 void BinaryQueue::AppendUnmanaged(const void* buffer,
132 BufferDeleter deleter,
135 // Do not attach empty buckets
136 if (bufferSize == 0) {
137 deleter(buffer, bufferSize, userParam);
141 // Just add new bucket with selected deleter
142 m_buckets.push_back(new Bucket(buffer, bufferSize, deleter, userParam));
144 // Increase total queue size
145 m_size += bufferSize;
148 size_t BinaryQueue::Size() const
153 bool BinaryQueue::Empty() const
158 void BinaryQueue::Consume(size_t size)
162 Throw(Exception::OutOfData);
165 size_t bytesLeft = size;
167 // Consume data and/or remove buckets
168 while (bytesLeft > 0) {
170 size_t count = std::min(bytesLeft, m_buckets.front()->left);
172 m_buckets.front()->ptr =
173 static_cast<const char *>(m_buckets.front()->ptr) + count;
174 m_buckets.front()->left -= count;
178 if (m_buckets.front()->left == 0) {
179 DeleteBucket(m_buckets.front());
180 m_buckets.pop_front();
185 void BinaryQueue::Flatten(void *buffer, size_t bufferSize) const
188 if (bufferSize == 0) {
192 if (bufferSize > m_size) {
193 Throw(Exception::OutOfData);
196 size_t bytesLeft = bufferSize;
198 BucketList::const_iterator bucketIterator = m_buckets.begin();
199 Assert(m_buckets.end() != bucketIterator);
202 while (bytesLeft > 0) {
204 size_t count = std::min(bytesLeft, (*bucketIterator)->left);
206 // Copy data to user pointer
207 memcpy(ptr, (*bucketIterator)->ptr, count);
209 // Update flattened bytes count
211 ptr = static_cast<char *>(ptr) + count;
218 void BinaryQueue::FlattenConsume(void *buffer, size_t bufferSize)
221 Flatten(buffer, bufferSize);
225 void BinaryQueue::DeleteBucket(BinaryQueue::Bucket *bucket)
230 void BinaryQueue::BufferDeleterFree(const void* data,
237 // Default free deleter
238 free(const_cast<void *>(data));
241 BinaryQueue::Bucket::Bucket(const void* data,
243 BufferDeleter dataDeleter,
249 deleter(dataDeleter),
252 Assert(data != NULL);
253 Assert(deleter != NULL);
256 BinaryQueue::Bucket::~Bucket()
258 // Invoke deleter on bucket data
259 deleter(buffer, size, param);
262 BinaryQueue::BucketVisitor::~BucketVisitor()
265 BinaryQueue::BucketVisitorCall::BucketVisitorCall(BucketVisitor *visitor) :
269 BinaryQueue::BucketVisitorCall::~BucketVisitorCall()
272 void BinaryQueue::BucketVisitorCall::operator()(Bucket *bucket) const
274 m_visitor->OnVisitBucket(bucket->ptr, bucket->left);
277 void BinaryQueue::VisitBuckets(BucketVisitor *visitor) const
279 Assert(visitor != NULL);
282 std::for_each(m_buckets.begin(), m_buckets.end(), BucketVisitorCall(visitor));
285 BinaryQueueAutoPtr BinaryQueue::Read(size_t size)
287 // Simulate input stream
288 size_t available = std::min(size, m_size);
290 std::unique_ptr<void,free_deleter> bufferCopy(malloc(available));
293 throw std::bad_alloc();
296 BinaryQueueAutoPtr result(new BinaryQueue());
298 Flatten(bufferCopy.get(), available);
299 result->AppendUnmanaged(
300 bufferCopy.get(), available, &BufferDeleterFree, NULL);
301 bufferCopy.release();
307 size_t BinaryQueue::Write(const BinaryQueue &buffer, size_t bufferSize)
309 // Simulate output stream
310 AppendCopyFrom(buffer);