2 * Copyright (c) 2011-2020 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>
32 BinaryQueue::BinaryQueue() :
36 BinaryQueue::BinaryQueue(const BinaryQueue &other) :
39 AppendCopyFrom(other);
42 BinaryQueue::~BinaryQueue()
44 // Remove all remainig buckets
48 const BinaryQueue &BinaryQueue::operator=(const BinaryQueue &other)
52 AppendCopyFrom(other);
58 void BinaryQueue::AppendCopyFrom(const BinaryQueue &other)
60 // To speed things up, always copy as one bucket
61 void *bufferCopy = malloc(other.m_size);
63 if (bufferCopy == NULL)
64 throw std::bad_alloc();
67 other.Flatten(bufferCopy, other.m_size);
68 AppendUnmanaged(bufferCopy, other.m_size, &BufferDeleterFree, NULL);
69 } catch (const std::bad_alloc &) {
70 // Free allocated memory
76 void BinaryQueue::AppendMoveFrom(BinaryQueue &other)
79 std::copy(other.m_buckets.begin(),
80 other.m_buckets.end(), std::back_inserter(m_buckets));
81 m_size += other.m_size;
83 // Clear other, but do not free memory
84 other.m_buckets.clear();
88 void BinaryQueue::AppendCopyTo(BinaryQueue &other) const
90 other.AppendCopyFrom(*this);
93 void BinaryQueue::AppendMoveTo(BinaryQueue &other)
95 other.AppendMoveFrom(*this);
98 void BinaryQueue::Clear()
100 std::for_each(m_buckets.begin(), m_buckets.end(), &DeleteBucket);
105 void BinaryQueue::AppendCopy(const void *buffer, size_t bufferSize)
107 // Create data copy with malloc/free
108 void *bufferCopy = malloc(bufferSize);
110 // Check if allocation succeded
111 if (bufferCopy == NULL)
112 throw std::bad_alloc();
115 memcpy(bufferCopy, buffer, bufferSize);
118 // Try to append new bucket
119 AppendUnmanaged(bufferCopy, bufferSize, &BufferDeleterFree, NULL);
120 } catch (const std::bad_alloc &) {
121 // Free allocated memory
127 void BinaryQueue::AppendUnmanaged(const void *buffer,
129 BufferDeleter deleter,
132 // Do not attach empty buckets
133 if (bufferSize == 0) {
134 deleter(buffer, bufferSize, userParam);
138 // Just add new bucket with selected deleter
139 Bucket *bucket = new Bucket(buffer, bufferSize, deleter, userParam);
142 m_buckets.push_back(bucket);
143 } catch (const std::bad_alloc &) {
148 // Increase total queue size
149 m_size += bufferSize;
152 size_t BinaryQueue::Size() const
157 bool BinaryQueue::Empty() const
162 void BinaryQueue::Consume(size_t size)
166 Throw(Exception::OutOfData);
168 size_t bytesLeft = size;
170 // Consume data and/or remove buckets
171 while (bytesLeft > 0) {
173 size_t count = std::min(bytesLeft, m_buckets.front()->left);
175 m_buckets.front()->ptr =
176 static_cast<const char *>(m_buckets.front()->ptr) + count;
177 m_buckets.front()->left -= count;
181 if (m_buckets.front()->left == 0) {
182 DeleteBucket(m_buckets.front());
183 m_buckets.pop_front();
188 void BinaryQueue::Flatten(void *buffer, size_t bufferSize) const
194 if (bufferSize > m_size)
195 Throw(Exception::OutOfData);
197 size_t bytesLeft = bufferSize;
199 BucketList::const_iterator bucketIterator = m_buckets.begin();
200 assert(m_buckets.end() != bucketIterator);
203 while (bytesLeft > 0) {
205 size_t count = std::min(bytesLeft, (*bucketIterator)->left);
207 // Copy data to user pointer
208 memcpy(ptr, (*bucketIterator)->ptr, count);
210 // Update flattened bytes count
212 ptr = static_cast<char *>(ptr) + count;
219 void BinaryQueue::FlattenConsume(void *buffer, size_t bufferSize)
222 Flatten(buffer, bufferSize);
226 void BinaryQueue::DeleteBucket(BinaryQueue::Bucket *bucket)
231 void BinaryQueue::BufferDeleterFree(const void *data,
238 // Default free deleter
239 free(const_cast<void *>(data));
242 BinaryQueue::Bucket::Bucket(const void *data,
244 BufferDeleter dataDeleter,
250 deleter(dataDeleter),
253 assert(data != NULL);
254 assert(deleter != NULL);
257 BinaryQueue::Bucket::~Bucket()
259 // Invoke deleter on bucket data
260 deleter(buffer, size, param);
263 BinaryQueue::BucketVisitor::~BucketVisitor()
267 BinaryQueue::BucketVisitorCall::BucketVisitorCall(BucketVisitor *visitor) :
272 BinaryQueue::BucketVisitorCall::~BucketVisitorCall()
276 void BinaryQueue::BucketVisitorCall::operator()(Bucket *bucket) const
278 m_visitor->OnVisitBucket(bucket->ptr, bucket->left);
281 void BinaryQueue::VisitBuckets(BucketVisitor *visitor) const
283 assert(visitor != NULL);
286 std::for_each(m_buckets.begin(), m_buckets.end(), BucketVisitorCall(visitor));
289 BinaryQueueUniquePtr BinaryQueue::Read(size_t size)
291 // Simulate input stream
292 size_t available = std::min(size, m_size);
294 std::unique_ptr<void, std::function<void(void *)>>
295 bufferCopy(malloc(available), free);
297 if (!bufferCopy.get())
298 throw std::bad_alloc();
300 BinaryQueueUniquePtr result(new BinaryQueue());
302 Flatten(bufferCopy.get(), available);
303 result->AppendUnmanaged(
304 bufferCopy.release(), available, &BufferDeleterFree, NULL);
310 size_t BinaryQueue::Write(const BinaryQueue &buffer, size_t bufferSize)
312 // Simulate output stream
313 AppendCopyFrom(buffer);