added iOS source code
[wl-app.git] / 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 (file)
index 0000000..024510e
--- /dev/null
@@ -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 <cstddef>
+#include <algorithm>
+#include <exception>
+#include <limits>
+#include <utility>
+
+#include <realm/util/features.h>
+#include <realm/utilities.hpp>
+#include <realm/util/safe_int_ops.hpp>
+#include <memory>
+
+namespace realm {
+namespace util {
+
+
+/// A simple buffer concept that owns a region of memory and knows its
+/// size.
+template <class T>
+class Buffer {
+public:
+    Buffer() noexcept
+        : m_size(0)
+    {
+    }
+    explicit Buffer(size_t initial_size);
+    Buffer(Buffer<T>&&) noexcept = default;
+    ~Buffer() noexcept
+    {
+    }
+
+    Buffer<T>& operator=(Buffer<T>&&) 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<T[]> 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 T>
+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<T> release() noexcept;
+
+private:
+    util::Buffer<T> m_buffer;
+    size_t m_size;
+};
+
+
+// Implementation:
+
+class BufferSizeOverflow : public std::exception {
+public:
+    const char* what() const noexcept override
+    {
+        return "Buffer size overflow";
+    }
+};
+
+template <class T>
+inline Buffer<T>::Buffer(size_t initial_size)
+    : m_data(new T[initial_size]) // Throws
+    , m_size(initial_size)
+{
+}
+
+template <class T>
+inline void Buffer<T>::set_size(size_t new_size)
+{
+    m_data.reset(new T[new_size]); // Throws
+    m_size = new_size;
+}
+
+template <class T>
+inline void Buffer<T>::resize(size_t new_size, size_t copy_begin, size_t copy_end, size_t copy_to)
+{
+    std::unique_ptr<T[]> 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 <class T>
+inline void Buffer<T>::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<size_t>::max();
+    new_capacity /= 2;
+
+    if (REALM_UNLIKELY(new_capacity < min_capacity))
+        new_capacity = min_capacity;
+    resize(new_capacity, 0, used_size, 0); // Throws
+}
+
+template <class T>
+inline void Buffer<T>::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 <class T>
+inline T* Buffer<T>::release() noexcept
+{
+    m_size = 0;
+    return m_data.release();
+}
+
+
+template <class T>
+inline AppendBuffer<T>::AppendBuffer() noexcept
+    : m_size(0)
+{
+}
+
+template <class T>
+inline size_t AppendBuffer<T>::size() const noexcept
+{
+    return m_size;
+}
+
+template <class T>
+inline T* AppendBuffer<T>::data() noexcept
+{
+    return m_buffer.data();
+}
+
+template <class T>
+inline const T* AppendBuffer<T>::data() const noexcept
+{
+    return m_buffer.data();
+}
+
+template <class T>
+inline void AppendBuffer<T>::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 <class T>
+inline void AppendBuffer<T>::reserve(size_t min_capacity)
+{
+    m_buffer.reserve(m_size, min_capacity);
+}
+
+template <class T>
+inline void AppendBuffer<T>::resize(size_t new_size)
+{
+    reserve(new_size);
+    m_size = new_size;
+}
+
+template <class T>
+inline void AppendBuffer<T>::clear() noexcept
+{
+    m_size = 0;
+}
+
+template <class T>
+inline Buffer<T> AppendBuffer<T>::release() noexcept
+{
+    m_size = 0;
+    return std::move(m_buffer);
+}
+
+
+} // namespace util
+} // namespace realm
+
+#endif // REALM_UTIL_BUFFER_HPP