/* * This file is open source software, licensed to you under the terms * of the Apache License, Version 2.0 (the "License"). See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. You may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Copyright (C) 2014 Cloudius Systems, Ltd. */ #ifndef TEMPORARY_BUFFER_HH_ #define TEMPORARY_BUFFER_HH_ #include "deleter.hh" #include "util/eclipse.hh" #include // A temporary_buffer either points inside a larger buffer, or, if the requested size // is too large, or if the larger buffer is scattered, contains its own storage. template class temporary_buffer { static_assert(sizeof(CharType) == 1, "must buffer stream of bytes"); CharType* _buffer; size_t _size; deleter _deleter; public: explicit temporary_buffer(size_t size) : _buffer(static_cast(malloc(size * sizeof(CharType)))), _size(size) , _deleter(make_free_deleter(_buffer)) { if (size && !_buffer) { throw std::bad_alloc(); } } //explicit temporary_buffer(CharType* borrow, size_t size) : _buffer(borrow), _size(size) {} temporary_buffer() : _buffer(nullptr) , _size(0) {} temporary_buffer(const temporary_buffer&) = delete; temporary_buffer(temporary_buffer&& x) : _buffer(x._buffer), _size(x._size), _deleter(std::move(x._deleter)) { x._buffer = nullptr; x._size = 0; } temporary_buffer(CharType* buf, size_t size, deleter d) : _buffer(buf), _size(size), _deleter(std::move(d)) {} void operator=(const temporary_buffer&) = delete; temporary_buffer& operator=(temporary_buffer&& x) { if (this != &x) { _buffer = x._buffer; _size = x._size; _deleter = std::move(x._deleter); x._buffer = nullptr; x._size = 0; } return *this; } const CharType* get() const { return _buffer; } CharType* get_write() { return _buffer; } size_t size() const { return _size; } const CharType* begin() { return _buffer; } const CharType* end() { return _buffer + _size; } temporary_buffer prefix(size_t size) && { auto ret = std::move(*this); ret._size = size; return ret; } CharType operator[](size_t pos) const { return _buffer[pos]; } bool empty() const { return !size(); } operator bool() { return size(); } temporary_buffer share() { return temporary_buffer(_buffer, _size, _deleter.share()); } temporary_buffer share(size_t pos, size_t len) { auto ret = share(); ret._buffer += pos; ret._size = len; return ret; } void trim_front(size_t pos) { _buffer += pos; _size -= pos; } void trim(size_t pos) { _size = pos; } deleter release() { return std::move(_deleter); } static temporary_buffer aligned(size_t alignment, size_t size) { auto buf = static_cast(::memalign(alignment, size * sizeof(CharType))); if (size && !buf) { throw std::bad_alloc(); } return temporary_buffer(buf, size, make_free_deleter(buf)); } }; #endif /* TEMPORARY_BUFFER_HH_ */