added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / column_mixed_tpl.hpp
diff --git a/iOS/Pods/Realm/include/core/realm/column_mixed_tpl.hpp b/iOS/Pods/Realm/include/core/realm/column_mixed_tpl.hpp
new file mode 100644 (file)
index 0000000..5afdddc
--- /dev/null
@@ -0,0 +1,514 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ **************************************************************************/
+
+#include <realm/column_binary.hpp>
+#include <realm/column_timestamp.hpp>
+
+namespace realm {
+
+inline MixedColumn::MixedColumn(Allocator& alloc, ref_type ref, Table* table, size_t column_ndx)
+    : ColumnBaseSimple(column_ndx)
+{
+    create(alloc, ref, table, column_ndx);
+}
+
+inline void MixedColumn::adj_acc_insert_rows(size_t row_ndx, size_t num_rows) noexcept
+{
+    m_data->adj_acc_insert_rows(row_ndx, num_rows);
+}
+
+inline void MixedColumn::adj_acc_erase_row(size_t row_ndx) noexcept
+{
+    m_data->adj_acc_erase_row(row_ndx);
+}
+
+inline void MixedColumn::adj_acc_swap_rows(size_t row_ndx_1, size_t row_ndx_2) noexcept
+{
+    m_data->adj_acc_swap_rows(row_ndx_1, row_ndx_2);
+}
+
+inline void MixedColumn::adj_acc_move_row(size_t from_ndx, size_t to_ndx) noexcept
+{
+    m_data->adj_acc_move_row(from_ndx, to_ndx);
+}
+
+inline void MixedColumn::adj_acc_move_over(size_t from_row_ndx, size_t to_row_ndx) noexcept
+{
+    m_data->adj_acc_move_over(from_row_ndx, to_row_ndx);
+}
+
+inline void MixedColumn::adj_acc_clear_root_table() noexcept
+{
+    m_data->adj_acc_clear_root_table();
+}
+
+inline ref_type MixedColumn::get_subtable_ref(size_t row_ndx) const noexcept
+{
+    REALM_ASSERT_3(row_ndx, <, m_types->size());
+    if (m_types->get(row_ndx) != type_Table)
+        return 0;
+    return m_data->get_as_ref(row_ndx);
+}
+
+inline size_t MixedColumn::get_subtable_size(size_t row_ndx) const noexcept
+{
+    ref_type top_ref = get_subtable_ref(row_ndx);
+    if (top_ref == 0)
+        return 0;
+    return _impl::TableFriend::get_size_from_ref(top_ref, m_data->get_alloc());
+}
+
+inline TableRef MixedColumn::get_subtable_accessor(size_t row_ndx) const noexcept
+{
+    return m_data->get_subtable_accessor(row_ndx);
+}
+
+inline void MixedColumn::discard_subtable_accessor(size_t row_ndx) noexcept
+{
+    m_data->discard_subtable_accessor(row_ndx);
+}
+
+inline TableRef MixedColumn::get_subtable_tableref(size_t row_ndx)
+{
+    REALM_ASSERT_3(row_ndx, <, m_types->size());
+    if (m_types->get(row_ndx) != type_Table)
+        return {};
+    return m_data->get_subtable_tableref(row_ndx); // Throws
+}
+
+inline ConstTableRef MixedColumn::get_subtable_tableref(size_t subtable_ndx) const
+{
+    return const_cast<MixedColumn*>(this)->get_subtable_tableref(subtable_ndx);
+}
+
+inline void MixedColumn::discard_child_accessors() noexcept
+{
+    m_data->discard_child_accessors();
+}
+
+
+//
+// Getters
+//
+
+#define REALM_BIT63 0x8000000000000000ULL
+
+inline int64_t MixedColumn::get_value(size_t ndx) const noexcept
+{
+    REALM_ASSERT_3(ndx, <, m_types->size());
+
+    // Shift the unsigned value right - ensuring 0 gets in from left.
+    // Shifting signed integers right doesn't ensure 0's.
+    uint64_t value = uint64_t(m_data->get(ndx)) >> 1;
+    return int64_t(value);
+}
+
+inline int64_t MixedColumn::get_int(size_t ndx) const noexcept
+{
+    // Get first 63 bits of the integer value
+    int64_t value = get_value(ndx);
+
+    // restore 'sign'-bit from the column-type
+    MixedColType col_type = MixedColType(m_types->get(ndx));
+    if (col_type == mixcol_IntNeg) {
+        // FIXME: Bad cast of result of '|' from unsigned to signed
+        value |= REALM_BIT63; // set sign bit (63)
+    }
+    else {
+        REALM_ASSERT_3(col_type, ==, mixcol_Int);
+    }
+    return value;
+}
+
+inline bool MixedColumn::get_bool(size_t ndx) const noexcept
+{
+    REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_Bool);
+
+    return (get_value(ndx) != 0);
+}
+
+inline OldDateTime MixedColumn::get_olddatetime(size_t ndx) const noexcept
+{
+    REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_OldDateTime);
+
+    return OldDateTime(get_value(ndx));
+}
+
+inline float MixedColumn::get_float(size_t ndx) const noexcept
+{
+    static_assert(std::numeric_limits<float>::is_iec559, "'float' is not IEEE");
+    static_assert((sizeof(float) * CHAR_BIT == 32), "Assume 32 bit float.");
+    REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_Float);
+
+    return type_punning<float>(get_value(ndx));
+}
+
+inline double MixedColumn::get_double(size_t ndx) const noexcept
+{
+    static_assert(std::numeric_limits<double>::is_iec559, "'double' is not IEEE");
+    static_assert((sizeof(double) * CHAR_BIT == 64), "Assume 64 bit double.");
+
+    int64_t int_val = get_value(ndx);
+
+    // restore 'sign'-bit from the column-type
+    MixedColType col_type = MixedColType(m_types->get(ndx));
+    if (col_type == mixcol_DoubleNeg)
+        int_val |= REALM_BIT63; // set sign bit (63)
+    else {
+        REALM_ASSERT_3(col_type, ==, mixcol_Double);
+    }
+    return type_punning<double>(int_val);
+}
+
+inline StringData MixedColumn::get_string(size_t ndx) const noexcept
+{
+    REALM_ASSERT_3(ndx, <, m_types->size());
+    REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_String);
+    REALM_ASSERT(m_binary_data);
+
+    size_t data_ndx = size_t(int64_t(m_data->get(ndx)) >> 1);
+    return m_binary_data->get_string(data_ndx);
+}
+
+inline BinaryData MixedColumn::get_binary(size_t ndx) const noexcept
+{
+    REALM_ASSERT_3(ndx, <, m_types->size());
+    REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_Binary);
+    REALM_ASSERT(m_binary_data);
+
+    size_t data_ndx = size_t(uint64_t(m_data->get(ndx)) >> 1);
+    return m_binary_data->get(data_ndx);
+}
+
+inline Timestamp MixedColumn::get_timestamp(size_t ndx) const noexcept
+{
+    REALM_ASSERT_3(ndx, <, m_types->size());
+    REALM_ASSERT_3(m_types->get(ndx), ==, mixcol_Timestamp);
+    REALM_ASSERT(m_timestamp_data);
+    size_t data_ndx = size_t(uint64_t(m_data->get(ndx)) >> 1);
+    return m_timestamp_data->get(data_ndx);
+}
+
+//
+// Setters
+//
+
+// Set a int64 value.
+// Store 63 bit of the value in m_data. Store sign bit in m_types.
+
+inline void MixedColumn::set_int64(size_t ndx, int64_t value, MixedColType pos_type, MixedColType neg_type)
+{
+    REALM_ASSERT_3(ndx, <, m_types->size());
+
+    // If sign-bit is set in value, 'store' it in the column-type
+    MixedColType coltype = ((value & REALM_BIT63) == 0) ? pos_type : neg_type;
+
+    // Remove refs or binary data (sets type to double)
+    clear_value_and_discard_subtab_acc(ndx, coltype); // Throws
+
+    // Shift value one bit and set lowest bit to indicate that this is not a ref
+    value = (value << 1) + 1;
+    m_data->set(ndx, value);
+}
+
+inline void MixedColumn::set_int(size_t ndx, int64_t value)
+{
+    set_int64(ndx, value, mixcol_Int, mixcol_IntNeg); // Throws
+}
+
+inline void MixedColumn::set_double(size_t ndx, double value)
+{
+    int64_t val64 = type_punning<int64_t>(value);
+    set_int64(ndx, val64, mixcol_Double, mixcol_DoubleNeg); // Throws
+}
+
+inline void MixedColumn::set_value(size_t ndx, int64_t value, MixedColType coltype)
+{
+    REALM_ASSERT_3(ndx, <, m_types->size());
+
+    // Remove refs or binary data (sets type to float)
+    clear_value_and_discard_subtab_acc(ndx, coltype); // Throws
+
+    // Shift value one bit and set lowest bit to indicate that this is not a ref
+    int64_t v = (value << 1) + 1;
+    m_data->set(ndx, v); // Throws
+}
+
+inline void MixedColumn::set_float(size_t ndx, float value)
+{
+    int64_t val64 = type_punning<int64_t>(value);
+    set_value(ndx, val64, mixcol_Float); // Throws
+}
+
+inline void MixedColumn::set_bool(size_t ndx, bool value)
+{
+    set_value(ndx, (value ? 1 : 0), mixcol_Bool); // Throws
+}
+
+inline void MixedColumn::set_olddatetime(size_t ndx, OldDateTime value)
+{
+    set_value(ndx, int64_t(value.get_olddatetime()), mixcol_OldDateTime); // Throws
+}
+
+inline void MixedColumn::set_subtable(size_t ndx, const Table* t)
+{
+    REALM_ASSERT_3(ndx, <, m_types->size());
+    typedef _impl::TableFriend tf;
+    ref_type ref;
+    if (t) {
+        ref = tf::clone(*t, get_alloc()); // Throws
+    }
+    else {
+        ref = tf::create_empty_table(get_alloc()); // Throws
+    }
+    // Remove any previous refs or binary data
+    clear_value_and_discard_subtab_acc(ndx, mixcol_Table); // Throws
+    m_data->set(ndx, ref);                                 // Throws
+}
+
+//
+// Inserts
+//
+
+inline void MixedColumn::insert_value(size_t row_ndx, int_fast64_t types_value, int_fast64_t data_value)
+{
+    size_t types_size = m_types->size(); // Slow
+    bool is_append = row_ndx == types_size;
+    size_t row_ndx_2 = is_append ? realm::npos : row_ndx;
+    size_t num_rows = 1;
+    m_types->insert_without_updating_index(row_ndx_2, types_value, num_rows); // Throws
+    m_data->do_insert(row_ndx_2, data_value, num_rows);                       // Throws
+}
+
+// Insert a int64 value.
+// Store 63 bit of the value in m_data. Store sign bit in m_types.
+
+inline void MixedColumn::insert_int(size_t ndx, int_fast64_t value, MixedColType type)
+{
+    int_fast64_t types_value = type;
+    // Shift value one bit and set lowest bit to indicate that this is not a ref
+    int_fast64_t data_value = 1 + (value << 1);
+    insert_value(ndx, types_value, data_value); // Throws
+}
+
+inline void MixedColumn::insert_pos_neg(size_t ndx, int_fast64_t value, MixedColType pos_type, MixedColType neg_type)
+{
+    // 'store' the sign-bit in the integer-type
+    MixedColType type = (value & REALM_BIT63) == 0 ? pos_type : neg_type;
+    int_fast64_t types_value = type;
+    // Shift value one bit and set lowest bit to indicate that this is not a ref
+    int_fast64_t data_value = 1 + (value << 1);
+    insert_value(ndx, types_value, data_value); // Throws
+}
+
+inline void MixedColumn::insert_int(size_t ndx, int_fast64_t value)
+{
+    insert_pos_neg(ndx, value, mixcol_Int, mixcol_IntNeg); // Throws
+}
+
+inline void MixedColumn::insert_double(size_t ndx, double value)
+{
+    int_fast64_t value_2 = type_punning<int64_t>(value);
+    insert_pos_neg(ndx, value_2, mixcol_Double, mixcol_DoubleNeg); // Throws
+}
+
+inline void MixedColumn::insert_float(size_t ndx, float value)
+{
+    int_fast64_t value_2 = type_punning<int32_t>(value);
+    insert_int(ndx, value_2, mixcol_Float); // Throws
+}
+
+inline void MixedColumn::insert_bool(size_t ndx, bool value)
+{
+    int_fast64_t value_2 = int_fast64_t(value);
+    insert_int(ndx, value_2, mixcol_Bool); // Throws
+}
+
+inline void MixedColumn::insert_olddatetime(size_t ndx, OldDateTime value)
+{
+    int_fast64_t value_2 = int_fast64_t(value.get_olddatetime());
+    insert_int(ndx, value_2, mixcol_OldDateTime); // Throws
+}
+
+inline void MixedColumn::insert_timestamp(size_t ndx, Timestamp value)
+{
+    ensure_timestamp_column();
+    size_t data_ndx = m_timestamp_data->size();
+    m_timestamp_data->add(value); // Throws
+    insert_int(ndx, int_fast64_t(data_ndx), mixcol_Timestamp);
+}
+
+inline void MixedColumn::insert_string(size_t ndx, StringData value)
+{
+    ensure_binary_data_column();
+    size_t blob_ndx = m_binary_data->size();
+    m_binary_data->add_string(value); // Throws
+
+    int_fast64_t value_2 = int_fast64_t(blob_ndx);
+    insert_int(ndx, value_2, mixcol_String); // Throws
+}
+
+inline void MixedColumn::insert_binary(size_t ndx, BinaryData value)
+{
+    ensure_binary_data_column();
+    size_t blob_ndx = m_binary_data->size();
+    m_binary_data->add(value); // Throws
+
+    int_fast64_t value_2 = int_fast64_t(blob_ndx);
+    insert_int(ndx, value_2, mixcol_Binary); // Throws
+}
+
+inline void MixedColumn::insert_subtable(size_t ndx, const Table* t)
+{
+    typedef _impl::TableFriend tf;
+    ref_type ref;
+    if (t) {
+        ref = tf::clone(*t, get_alloc()); // Throws
+    }
+    else {
+        ref = tf::create_empty_table(get_alloc()); // Throws
+    }
+    int_fast64_t types_value = mixcol_Table;
+    int_fast64_t data_value = int_fast64_t(ref);
+    insert_value(ndx, types_value, data_value); // Throws
+}
+
+inline void MixedColumn::erase(size_t row_ndx)
+{
+    size_t num_rows_to_erase = 1;
+    size_t prior_num_rows = size();                       // Note that size() is slow
+    do_erase(row_ndx, num_rows_to_erase, prior_num_rows); // Throws
+}
+
+inline void MixedColumn::move_last_over(size_t row_ndx)
+{
+    size_t prior_num_rows = size();             // Note that size() is slow
+    do_move_last_over(row_ndx, prior_num_rows); // Throws
+}
+
+inline void MixedColumn::swap_rows(size_t row_ndx_1, size_t row_ndx_2)
+{
+    do_swap_rows(row_ndx_1, row_ndx_2);
+}
+
+inline void MixedColumn::clear()
+{
+    size_t num_rows = size(); // Note that size() is slow
+    do_clear(num_rows);       // Throws
+}
+
+inline size_t MixedColumn::get_size_from_ref(ref_type root_ref, Allocator& alloc) noexcept
+{
+    const char* root_header = alloc.translate(root_ref);
+    ref_type types_ref = to_ref(Array::get(root_header, 0));
+    return IntegerColumn::get_size_from_ref(types_ref, alloc);
+}
+
+inline void MixedColumn::clear_value_and_discard_subtab_acc(size_t row_ndx, MixedColType new_type)
+{
+    MixedColType old_type = clear_value(row_ndx, new_type);
+    if (old_type == mixcol_Table)
+        m_data->discard_subtable_accessor(row_ndx);
+}
+
+// Implementing pure virtual method of ColumnBase.
+inline void MixedColumn::insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows,
+                                     bool insert_nulls)
+{
+    REALM_ASSERT_DEBUG(prior_num_rows == size());
+    REALM_ASSERT(row_ndx <= prior_num_rows);
+    REALM_ASSERT(!insert_nulls);
+
+    size_t row_ndx_2 = (row_ndx == prior_num_rows ? realm::npos : row_ndx);
+
+    int_fast64_t type_value = mixcol_Int;
+    m_types->insert_without_updating_index(row_ndx_2, type_value, num_rows_to_insert); // Throws
+
+    // The least significant bit indicates that the rest of the bits form an
+    // integer value, so 1 is actually zero.
+    int_fast64_t data_value = 1;
+    m_data->do_insert(row_ndx_2, data_value, num_rows_to_insert); // Throws
+}
+
+// Implementing pure virtual method of ColumnBase.
+inline void MixedColumn::erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows, bool)
+{
+    do_erase(row_ndx, num_rows_to_erase, prior_num_rows); // Throws
+}
+
+// Implementing pure virtual method of ColumnBase.
+inline void MixedColumn::move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool)
+{
+    do_move_last_over(row_ndx, prior_num_rows); // Throws
+}
+
+// Implementing pure virtual method of ColumnBase.
+inline void MixedColumn::clear(size_t num_rows, bool)
+{
+    do_clear(num_rows); // Throws
+}
+
+inline void MixedColumn::mark(int type) noexcept
+{
+    m_data->mark(type);
+}
+
+inline void MixedColumn::refresh_accessor_tree(size_t col_ndx, const Spec& spec)
+{
+    ColumnBaseSimple::refresh_accessor_tree(col_ndx, spec);
+
+    get_root_array()->init_from_parent();
+    m_types->refresh_accessor_tree(col_ndx, spec); // Throws
+    m_data->refresh_accessor_tree(col_ndx, spec);  // Throws
+
+    m_binary_data.reset();
+    // See if m_binary_data needs to be created.
+    if (get_root_array()->size() >= 3) {
+        ref_type ref = get_root_array()->get_as_ref(2);
+        m_binary_data.reset(new BinaryColumn(get_alloc(), ref)); // Throws
+        m_binary_data->set_parent(get_root_array(), 2);
+    }
+
+    m_timestamp_data.reset();
+    // See if m_timestamp_data needs to be created.
+    if (get_root_array()->size() >= 4) {
+        ref_type ref = get_root_array()->get_as_ref(3);
+        // When adding/creating a Mixed column the user cannot specify nullability, so the "true" below
+        // makes it implicitly nullable, which may not be wanted. But it's OK since Mixed columns are not
+        // publicly supported
+        m_timestamp_data.reset(new TimestampColumn(true /*fixme*/, get_alloc(), ref)); // Throws
+        m_timestamp_data->set_parent(get_root_array(), 3);
+    }
+
+    if (m_binary_data) {
+        REALM_ASSERT_3(get_root_array()->size(), >=, 3);
+        m_binary_data->refresh_accessor_tree(col_ndx, spec); // Throws
+    }
+    if (m_timestamp_data) {
+        REALM_ASSERT_3(get_root_array()->size(), >=, 4);
+        m_timestamp_data->refresh_accessor_tree(col_ndx, spec); // Throws
+    }
+}
+
+inline void MixedColumn::RefsColumn::refresh_accessor_tree(size_t col_ndx, const Spec& spec)
+{
+    SubtableColumnBase::refresh_accessor_tree(col_ndx, spec); // Throws
+    m_subtable_map.refresh_accessor_tree();                   // Throws
+}
+
+} // namespace realm