inline void Descriptor::insert_column_link(size_t col_ndx, DataType type, StringData name, Table& target, LinkType link_type) { typedef _impl::TableFriend tf; if (REALM_UNLIKELY(!is_attached() || !target.is_attached())) throw LogicError(LogicError::detached_accessor); if (REALM_UNLIKELY(col_ndx > get_column_count())) throw LogicError(LogicError::column_index_out_of_range); if (REALM_UNLIKELY(!tf::is_link_type(ColumnType(type)))) throw LogicError(LogicError::illegal_type); if (REALM_UNLIKELY(!is_root())) throw LogicError(LogicError::wrong_kind_of_descriptor); // Both origin and target must be group-level tables, and in the same group. Group* origin_group = tf::get_parent_group(*get_root_table()); Group* target_group = tf::get_parent_group(target); if (!origin_group || !target_group) throw LogicError(LogicError::wrong_kind_of_table); if (origin_group != target_group) throw LogicError(LogicError::group_mismatch); LinkTargetInfo link(&target); tf::insert_column(*this, col_ndx, type, name, link); // Throws adj_insert_column(col_ndx); tf::set_link_type(*get_root_table(), col_ndx, link_type); // Throws }
inline size_t Utf8x16<Char16, Traits16>::find_utf8_buf_size(const Char16*& in_begin, const Char16* const in_end) { size_t num_out = 0; const Char16* in = in_begin; while (in != in_end) { REALM_ASSERT(&in[0] >= in_begin && &in[0] < in_end); uint_fast16_t v = uint_fast16_t(Traits16::to_int_type(in[0])); if (REALM_LIKELY(v < 0x80)) { if (REALM_UNLIKELY(int_add_with_overflow_detect(num_out, 1))) break; // Avoid overflow in += 1; } else if (REALM_LIKELY(v < 0x800)) { if (REALM_UNLIKELY(int_add_with_overflow_detect(num_out, 2))) break; // Avoid overflow in += 1; } else if (REALM_LIKELY(v < 0xD800 || 0xE000 <= v)) { if (REALM_UNLIKELY(int_add_with_overflow_detect(num_out, 3))) break; // Avoid overflow in += 1; } else { if (REALM_UNLIKELY(in + 1 == in_end)) { break; // Incomplete surrogate pair } if (REALM_UNLIKELY(int_add_with_overflow_detect(num_out, 4))) break; // Avoid overflow in += 2; } } REALM_ASSERT(in >= in_begin && in <= in_end); in_begin = in; return num_out; }
inline void Descriptor::rename_column(size_t col_ndx, StringData name) { typedef _impl::TableFriend tf; if (REALM_UNLIKELY(!is_attached())) throw LogicError(LogicError::detached_accessor); if (REALM_UNLIKELY(col_ndx >= get_column_count())) throw LogicError(LogicError::column_index_out_of_range); tf::rename_column(*this, col_ndx, name); // Throws }
inline void Descriptor::set_link_type(size_t col_ndx, LinkType link_type) { typedef _impl::TableFriend tf; if (REALM_UNLIKELY(!is_attached())) throw LogicError(LogicError::detached_accessor); if (REALM_UNLIKELY(col_ndx >= get_column_count())) throw LogicError(LogicError::column_index_out_of_range); if (REALM_UNLIKELY(!tf::is_link_type(ColumnType(get_column_type(col_ndx))))) throw LogicError(LogicError::illegal_type); tf::set_link_type(*get_root_table(), col_ndx, link_type); // Throws }
inline size_t Utf8x16<Char16, Traits16>::find_utf16_buf_size(const char*& in_begin, const char* const in_end) { typedef std::char_traits<char> traits8; size_t num_out = 0; const char* in = in_begin; while (in != in_end) { REALM_ASSERT(&in[0] >= in_begin && &in[0] < in_end); uint_fast16_t v1 = uint_fast16_t(traits8::to_int_type(in[0])); if (REALM_LIKELY(v1 < 0x80)) { // One byte num_out += 1; in += 1; continue; } if (REALM_UNLIKELY(v1 < 0xC0)) { break; // Invalid first byte of UTF-8 sequence } if (REALM_LIKELY(v1 < 0xE0)) { // Two bytes if (REALM_UNLIKELY(in_end - in < 2)) { break; // Incomplete UTF-8 sequence } num_out += 1; in += 2; continue; } if (REALM_LIKELY(v1 < 0xF0)) { // Three bytes if (REALM_UNLIKELY(in_end - in < 3)) { break; // Incomplete UTF-8 sequence } num_out += 1; in += 3; continue; } if (REALM_LIKELY(v1 < 0xF8)) { // Four bytes if (REALM_UNLIKELY(in_end - in < 4)) { break; // Incomplete UTF-8 sequence } num_out += 2; // Surrogate pair in += 4; continue; } // Invalid first byte of UTF-8 sequence, or code point too big for UTF-16 break; } REALM_ASSERT(in >= in_begin && in <= in_end); in_begin = in; return num_out; }
inline size_t ChangesetInputStream::next_block(const char*& begin, const char*& end) { for (;;) { if (REALM_UNLIKELY(m_changesets_begin == m_changesets_end)) { if (m_begin_version == m_end_version) return 0; // End of input version_type n = sizeof m_changesets / sizeof m_changesets[0]; version_type avail = m_end_version - m_begin_version; if (n > avail) n = avail; version_type end_version = m_begin_version + n; m_history.get_changesets(m_begin_version, end_version, m_changesets); m_begin_version = end_version; m_changesets_begin = m_changesets; m_changesets_end = m_changesets_begin + n; } BinaryData changeset = *m_changesets_begin++; if (changeset.size() > 0) { begin = changeset.data(); end = changeset.data() + changeset.size(); return changeset.size(); } } }
inline void Descriptor::insert_column(size_t col_ndx, DataType type, StringData name, DescriptorRef* subdesc, bool nullable) { typedef _impl::TableFriend tf; if (REALM_UNLIKELY(!is_attached())) throw LogicError(LogicError::detached_accessor); if (REALM_UNLIKELY(col_ndx > get_column_count())) throw LogicError(LogicError::column_index_out_of_range); if (REALM_UNLIKELY(tf::is_link_type(ColumnType(type)))) throw LogicError(LogicError::illegal_type); LinkTargetInfo invalid_link; tf::insert_column(*this, col_ndx, type, name, invalid_link, nullable); // Throws adj_insert_column(col_ndx); if (subdesc && type == type_Table) *subdesc = get_subdescriptor(col_ndx); }
bool next_block(const char*& begin, const char*& end) override { while (m_valid) { BinaryData actual = m_changesets_begin->get_next(); if (actual.size() > 0) { begin = actual.data(); end = actual.data() + actual.size(); return true; } m_changesets_begin++; if (REALM_UNLIKELY(m_changesets_begin == m_changesets_end)) { get_changeset(); } } return false; // End of input }
inline bool Utf8x16<Char16, Traits16>::to_utf16(const char*& in_begin, const char* const in_end, Char16*& out_begin, Char16* const out_end) { typedef std::char_traits<char> traits8; bool invalid = false; const char* in = in_begin; Char16* out = out_begin; while (in != in_end) { if (REALM_UNLIKELY(out == out_end)) { break; // Need space in output buffer } REALM_ASSERT(&in[0] >= in_begin && &in[0] < in_end); uint_fast16_t v1 = uint_fast16_t(traits8::to_int_type(in[0])); if (REALM_LIKELY(v1 < 0x80)) { // One byte // UTF-8 layout: 0xxxxxxx *out++ = Traits16::to_char_type(v1); in += 1; continue; } if (REALM_UNLIKELY(v1 < 0xC0)) { invalid = true; break; // Invalid first byte of UTF-8 sequence } if (REALM_LIKELY(v1 < 0xE0)) { // Two bytes if (REALM_UNLIKELY(in_end - in < 2)) { invalid = true; break; // Incomplete UTF-8 sequence } REALM_ASSERT(&in[1] >= in_begin && &in[1] < in_end); uint_fast16_t v2 = uint_fast16_t(traits8::to_int_type(in[1])); // UTF-8 layout: 110xxxxx 10xxxxxx if (REALM_UNLIKELY((v2 & 0xC0) != 0x80)) { invalid = true; break; // Invalid continuation byte } uint_fast16_t v = uint_fast16_t(((v1 & 0x1F) << 6) | ((v2 & 0x3F) << 0)); if (REALM_UNLIKELY(v < 0x80)) { invalid = true; break; // Overlong encoding is invalid } *out++ = Traits16::to_char_type(v); in += 2; continue; } if (REALM_LIKELY(v1 < 0xF0)) { // Three bytes if (REALM_UNLIKELY(in_end - in < 3)) { invalid = true; break; // Incomplete UTF-8 sequence } REALM_ASSERT(&in[1] >= in_begin && &in[2] < in_end); uint_fast16_t v2 = uint_fast16_t(traits8::to_int_type(in[1])); uint_fast16_t v3 = uint_fast16_t(traits8::to_int_type(in[2])); // UTF-8 layout: 1110xxxx 10xxxxxx 10xxxxxx if (REALM_UNLIKELY((v2 & 0xC0) != 0x80 || (v3 & 0xC0) != 0x80)) { invalid = true; break; // Invalid continuation byte } uint_fast16_t v = uint_fast16_t(((v1 & 0x0F) << 12) | ((v2 & 0x3F) << 6) | ((v3 & 0x3F) << 0)); if (REALM_UNLIKELY(v < 0x800)) { invalid = true; break; // Overlong encoding is invalid } if (REALM_UNLIKELY(0xD800 <= v && v < 0xE000)) { invalid = true; break; // Illegal code point range (reserved for UTF-16 surrogate pairs) } *out++ = Traits16::to_char_type(v); in += 3; continue; } if (REALM_UNLIKELY(out + 1 == out_end)) { break; // Need space in output buffer for surrogate pair } if (REALM_LIKELY(v1 < 0xF8)) { // Four bytes if (REALM_UNLIKELY(in_end - in < 4)) { invalid = true; break; // Incomplete UTF-8 sequence } uint_fast32_t w1 = uint_fast32_t(v1); // 16 bit -> 32 bit REALM_ASSERT(&in[1] >= in_begin && &in[3] < in_end); uint_fast32_t v2 = uint_fast32_t(traits8::to_int_type(in[1])); // 32 bit intended uint_fast16_t v3 = uint_fast16_t(traits8::to_int_type(in[2])); // 16 bit intended uint_fast16_t v4 = uint_fast16_t(traits8::to_int_type(in[3])); // 16 bit intended // UTF-8 layout: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx if (REALM_UNLIKELY((v2 & 0xC0) != 0x80 || (v3 & 0xC0) != 0x80 || (v4 & 0xC0) != 0x80)) { invalid = true; break; // Invalid continuation byte } uint_fast32_t v = uint_fast32_t(((w1 & 0x07) << 18) | // Parenthesis is 32 bit partial result ((v2 & 0x3F) << 12) | // Parenthesis is 32 bit partial result ((v3 & 0x3F) << 6) | // Parenthesis is 16 bit partial result ((v4 & 0x3F) << 0)); // Parenthesis is 16 bit partial result if (REALM_UNLIKELY(v < 0x10000)) { invalid = true; break; // Overlong encoding is invalid } if (REALM_UNLIKELY(0x110000 <= v)) { invalid = true; break; // Code point too big for UTF-16 } v -= 0x10000l; *out++ = Traits16::to_char_type(0xD800 + (v / 0x400)); *out++ = Traits16::to_char_type(0xDC00 + (v % 0x400)); in += 4; continue; } // Invalid first byte of UTF-8 sequence, or code point too big for UTF-16 invalid = true; break; } REALM_ASSERT(in >= in_begin && in <= in_end); REALM_ASSERT(out >= out_begin && out <= out_end); in_begin = in; out_begin = out; return !invalid; }
inline bool Utf8x16<Char16, Traits16>::to_utf8(const Char16*& in_begin, const Char16* const in_end, char*& out_begin, char* const out_end) { typedef std::char_traits<char> traits8; typedef typename traits8::int_type traits8_int_type; bool invalid = false; const Char16* in = in_begin; char* out = out_begin; while (in != in_end) { REALM_ASSERT(&in[0] >= in_begin && &in[0] < in_end); uint_fast16_t v1 = uint_fast16_t(Traits16::to_int_type(in[0])); if (REALM_LIKELY(v1 < 0x80)) { if (REALM_UNLIKELY(out == out_end)) { break; // Not enough output buffer space } // UTF-8 layout: 0xxxxxxx REALM_ASSERT(out >= out_begin && out < out_end); *out++ = traits8::to_char_type(traits8_int_type(v1)); in += 1; continue; } if (REALM_LIKELY(v1 < 0x800)) { if (REALM_UNLIKELY(out_end - out < 2)) { break; // Not enough output buffer space } // UTF-8 layout: 110xxxxx 10xxxxxx *out++ = traits8::to_char_type(traits8_int_type(0xC0 + v1 / 0x40)); REALM_ASSERT(out >= out_begin && out < out_end); *out++ = traits8::to_char_type(traits8_int_type(0x80 + v1 % 0x40)); in += 1; continue; } if (REALM_LIKELY(v1 < 0xD800 || 0xE000 <= v1)) { if (REALM_UNLIKELY(out_end - out < 3)) { break; // Not enough output buffer space } // UTF-8 layout: 1110xxxx 10xxxxxx 10xxxxxx REALM_ASSERT(out >= out_begin && out + 2 < out_end); *out++ = traits8::to_char_type(traits8_int_type(0xE0 + v1 / 0x1000)); *out++ = traits8::to_char_type(traits8_int_type(0x80 + v1 / 0x40 % 0x40)); *out++ = traits8::to_char_type(traits8_int_type(0x80 + v1 % 0x40)); in += 1; continue; } // Surrogate pair if (REALM_UNLIKELY(out_end - out < 4)) { break; // Not enough output buffer space } if (REALM_UNLIKELY(0xDC00 <= v1)) { invalid = true; break; // Invalid first half of surrogate pair } if (REALM_UNLIKELY(in + 1 == in_end)) { invalid = true; break; // Incomplete surrogate pair } REALM_ASSERT(&in[1] >= in_begin && &in[1] < in_end); uint_fast16_t v2 = uint_fast16_t(Traits16::to_int_type(in[1])); if (REALM_UNLIKELY(v2 < 0xDC00 || 0xE000 <= v2)) { invalid = true; break; // Invalid second half of surrogate pair } uint_fast32_t v = 0x10000l + (uint_fast32_t(v1 - 0xD800) * 0x400 + (v2 - 0xDC00)); // UTF-8 layout: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx REALM_ASSERT(out >= out_begin && out + 3 < out_end); *out++ = traits8::to_char_type(traits8_int_type(0xF0 + v / 0x40000)); *out++ = traits8::to_char_type(traits8_int_type(0x80 + v / 0x1000 % 0x40)); *out++ = traits8::to_char_type(traits8_int_type(0x80 + v / 0x40 % 0x40)); *out++ = traits8::to_char_type(traits8_int_type(0x80 + v % 0x40)); in += 2; } REALM_ASSERT(in >= in_begin && in <= in_end); REALM_ASSERT(out >= out_begin && out <= out_end); in_begin = in; out_begin = out; return !invalid; }