X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/53b27422d140022594fc241cca91c3183be57bca..48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff:/iOS/Pods/Realm/include/core/realm/util/buffer.hpp diff --git a/iOS/Pods/Realm/include/core/realm/util/buffer.hpp b/iOS/Pods/Realm/include/core/realm/util/buffer.hpp new file mode 100644 index 0000000..024510e --- /dev/null +++ b/iOS/Pods/Realm/include/core/realm/util/buffer.hpp @@ -0,0 +1,301 @@ +/************************************************************************* + * + * Copyright 2016 Realm Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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. + * + **************************************************************************/ + +#ifndef REALM_UTIL_BUFFER_HPP +#define REALM_UTIL_BUFFER_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace realm { +namespace util { + + +/// A simple buffer concept that owns a region of memory and knows its +/// size. +template +class Buffer { +public: + Buffer() noexcept + : m_size(0) + { + } + explicit Buffer(size_t initial_size); + Buffer(Buffer&&) noexcept = default; + ~Buffer() noexcept + { + } + + Buffer& operator=(Buffer&&) noexcept = default; + + T& operator[](size_t i) noexcept + { + return m_data[i]; + } + const T& operator[](size_t i) const noexcept + { + return m_data[i]; + } + + T* data() noexcept + { + return m_data.get(); + } + const T* data() const noexcept + { + return m_data.get(); + } + size_t size() const noexcept + { + return m_size; + } + + /// False iff the data() returns null. + explicit operator bool() const noexcept + { + return bool(m_data); + } + + /// Discards the original contents. + void set_size(size_t new_size); + + /// \param new_size Specifies the new buffer size. + /// \param copy_begin, copy_end Specifies a range of element + /// values to be retained. \a copy_end must be less than, or equal + /// to size(). + /// + /// \param copy_to Specifies where the retained range should be + /// copied to. `\a copy_to + \a copy_end - \a copy_begin` must be + /// less than, or equal to \a new_size. + void resize(size_t new_size, size_t copy_begin, size_t copy_end, size_t copy_to); + + void reserve(size_t used_size, size_t min_capacity); + + void reserve_extra(size_t used_size, size_t min_extra_capacity); + + T* release() noexcept; + + friend void swap(Buffer& a, Buffer& b) noexcept + { + using std::swap; + swap(a.m_data, b.m_data); + swap(a.m_size, b.m_size); + } + +private: + std::unique_ptr m_data; + size_t m_size; +}; + + +/// A buffer that can be efficiently resized. It acheives this by +/// using an underlying buffer that may be larger than the logical +/// size, and is automatically expanded in progressively larger steps. +template +class AppendBuffer { +public: + AppendBuffer() noexcept; + ~AppendBuffer() noexcept + { + } + + AppendBuffer(AppendBuffer&&) noexcept = default; + AppendBuffer& operator=(AppendBuffer&&) noexcept = default; + + /// Returns the current size of the buffer. + size_t size() const noexcept; + + /// Gives read and write access to the elements. + T* data() noexcept; + + /// Gives read access the elements. + const T* data() const noexcept; + + /// Append the specified elements. This increases the size of this + /// buffer by \a append_data_size. If the caller has previously requested + /// a minimum capacity that is greater than, or equal to the + /// resulting size, this function is guaranteed to not throw. + void append(const T* append_data, size_t append_data_size); + + /// If the specified size is less than the current size, then the + /// buffer contents is truncated accordingly. If the specified + /// size is greater than the current size, then the extra elements + /// will have undefined values. If the caller has previously + /// requested a minimum capacity that is greater than, or equal to + /// the specified size, this function is guaranteed to not throw. + void resize(size_t new_size); + + /// This operation does not change the size of the buffer as + /// returned by size(). If the specified capacity is less than the + /// current capacity, this operation has no effect. + void reserve(size_t min_capacity); + + /// Set the size to zero. The capacity remains unchanged. + void clear() noexcept; + + /// Release the underlying buffer and reset the size. Note: The returned + /// buffer may be larger than the amount of data appended to this buffer. + /// Callers should call `size()` prior to releasing the buffer to know the + /// usable/logical size. + Buffer release() noexcept; + +private: + util::Buffer m_buffer; + size_t m_size; +}; + + +// Implementation: + +class BufferSizeOverflow : public std::exception { +public: + const char* what() const noexcept override + { + return "Buffer size overflow"; + } +}; + +template +inline Buffer::Buffer(size_t initial_size) + : m_data(new T[initial_size]) // Throws + , m_size(initial_size) +{ +} + +template +inline void Buffer::set_size(size_t new_size) +{ + m_data.reset(new T[new_size]); // Throws + m_size = new_size; +} + +template +inline void Buffer::resize(size_t new_size, size_t copy_begin, size_t copy_end, size_t copy_to) +{ + std::unique_ptr new_data(new T[new_size]); // Throws + realm::safe_copy_n(m_data.get() + copy_begin, copy_end - copy_begin, new_data.get() + copy_to); + m_data.reset(new_data.release()); + m_size = new_size; +} + +template +inline void Buffer::reserve(size_t used_size, size_t min_capacity) +{ + size_t current_capacity = m_size; + if (REALM_LIKELY(current_capacity >= min_capacity)) + return; + size_t new_capacity = current_capacity; + + // Use growth factor 1.5. + if (REALM_UNLIKELY(int_multiply_with_overflow_detect(new_capacity, 3))) + new_capacity = std::numeric_limits::max(); + new_capacity /= 2; + + if (REALM_UNLIKELY(new_capacity < min_capacity)) + new_capacity = min_capacity; + resize(new_capacity, 0, used_size, 0); // Throws +} + +template +inline void Buffer::reserve_extra(size_t used_size, size_t min_extra_capacity) +{ + size_t min_capacity = used_size; + if (REALM_UNLIKELY(int_add_with_overflow_detect(min_capacity, min_extra_capacity))) + throw BufferSizeOverflow(); + reserve(used_size, min_capacity); // Throws +} + +template +inline T* Buffer::release() noexcept +{ + m_size = 0; + return m_data.release(); +} + + +template +inline AppendBuffer::AppendBuffer() noexcept + : m_size(0) +{ +} + +template +inline size_t AppendBuffer::size() const noexcept +{ + return m_size; +} + +template +inline T* AppendBuffer::data() noexcept +{ + return m_buffer.data(); +} + +template +inline const T* AppendBuffer::data() const noexcept +{ + return m_buffer.data(); +} + +template +inline void AppendBuffer::append(const T* append_data, size_t append_data_size) +{ + m_buffer.reserve_extra(m_size, append_data_size); // Throws + realm::safe_copy_n(append_data, append_data_size, m_buffer.data() + m_size); + m_size += append_data_size; +} + +template +inline void AppendBuffer::reserve(size_t min_capacity) +{ + m_buffer.reserve(m_size, min_capacity); +} + +template +inline void AppendBuffer::resize(size_t new_size) +{ + reserve(new_size); + m_size = new_size; +} + +template +inline void AppendBuffer::clear() noexcept +{ + m_size = 0; +} + +template +inline Buffer AppendBuffer::release() noexcept +{ + m_size = 0; + return std::move(m_buffer); +} + + +} // namespace util +} // namespace realm + +#endif // REALM_UTIL_BUFFER_HPP