<commit_before>#include <realm/sync/changeset.hpp>

#if REALM_DEBUG
#include <iostream>
#include <iomanip>
#include <sstream>
#endif // REALM_DEBUG

using namespace realm;
using namespace realm::sync;
using namespace realm::util;

Changeset::Changeset()
{
    m_strings = std::make_shared<InternStrings>();
    m_string_buffer = std::make_shared<StringBuffer>();
}

Changeset::Changeset(const Changeset& other, share_buffers_tag)
    : version(other.version)
    , last_integrated_remote_version(other.last_integrated_remote_version)
    , origin_timestamp(other.origin_timestamp)
    , origin_file_ident(other.origin_file_ident)
{
    m_strings = other.m_strings;
    m_string_buffer = other.m_string_buffer;
}

InternString Changeset::intern_string(StringData str)
{
    if (InternString interned = find_string(str))
        return interned;

    REALM_ASSERT(m_string_buffer->size() < std::numeric_limits<uint32_t>::max());
    REALM_ASSERT(m_strings->size() < std::numeric_limits<uint32_t>::max());
    REALM_ASSERT(str.size() < std::numeric_limits<uint32_t>::max());

    // FIXME: Very slow.
    uint32_t size = uint32_t(str.size());
    uint32_t offset = uint32_t(m_string_buffer->size());
    m_string_buffer->append(str.data(), size);
    uint32_t index = uint32_t(m_strings->size());
    m_strings->push_back(StringBufferRange{offset, size});
    return InternString{index};
}


InternString Changeset::find_string(StringData string) const noexcept
{
    // FIXME: Linear search can be very expensive as changesets can be very big
    std::size_t n = m_strings->size();
    for (std::size_t i = 0; i < n; ++i) {
        const auto& range = (*m_strings)[i];
        StringData string_2{m_string_buffer->data() + range.offset, range.size};
        if (string_2 == string)
            return InternString{std::uint_least32_t(i)};
    }
    return InternString{};
}

#pragma runtime_checks("", off)
PrimaryKey Changeset::get_key(const Instruction::PrimaryKey& key) const noexcept
{
    const auto& get = overload{
        [this](InternString str) -> PrimaryKey {
            return get_string(str);
        },
        [](auto otherwise) -> PrimaryKey {
            return otherwise;
        },
    };
    return mpark::visit(get, key);
}
#pragma runtime_checks("", restore)

bool Changeset::operator==(const Changeset& that) const noexcept
{
    if (m_instructions == that.m_instructions) {
        return *m_strings == *that.m_strings;
    }
    return false;
}

std::ostream& Changeset::print_value(std::ostream& os, const Instruction::Payload& value) const noexcept
{
    using Type = Instruction::Payload::Type;

    os << get_type_name(value.type) << "(";
    auto& data = value.data;
    switch (value.type) {
        case Type::ObjectValue:
            break;
        case Type::GlobalKey:
            os << data.key;
            break;
        case Type::Erased:<commit_msg>Only disable checks for MSVC<commit_after>#include <realm/sync/changeset.hpp>

#if REALM_DEBUG
#include <iostream>
#include <iomanip>
#include <sstream>
#endif // REALM_DEBUG

using namespace realm;
using namespace realm::sync;
using namespace realm::util;

Changeset::Changeset()
{
    m_strings = std::make_shared<InternStrings>();
    m_string_buffer = std::make_shared<StringBuffer>();
}

Changeset::Changeset(const Changeset& other, share_buffers_tag)
    : version(other.version)
    , last_integrated_remote_version(other.last_integrated_remote_version)
    , origin_timestamp(other.origin_timestamp)
    , origin_file_ident(other.origin_file_ident)
{
    m_strings = other.m_strings;
    m_string_buffer = other.m_string_buffer;
}

InternString Changeset::intern_string(StringData str)
{
    if (InternString interned = find_string(str))
        return interned;

    REALM_ASSERT(m_string_buffer->size() < std::numeric_limits<uint32_t>::max());
    REALM_ASSERT(m_strings->size() < std::numeric_limits<uint32_t>::max());
    REALM_ASSERT(str.size() < std::numeric_limits<uint32_t>::max());

    // FIXME: Very slow.
    uint32_t size = uint32_t(str.size());
    uint32_t offset = uint32_t(m_string_buffer->size());
    m_string_buffer->append(str.data(), size);
    uint32_t index = uint32_t(m_strings->size());
    m_strings->push_back(StringBufferRange{offset, size});
    return InternString{index};
}


InternString Changeset::find_string(StringData string) const noexcept
{
    // FIXME: Linear search can be very expensive as changesets can be very big
    std::size_t n = m_strings->size();
    for (std::size_t i = 0; i < n; ++i) {
        const auto& range = (*m_strings)[i];
        StringData string_2{m_string_buffer->data() + range.offset, range.size};
        if (string_2 == string)
            return InternString{std::uint_least32_t(i)};
    }
    return InternString{};
}

#if _MSC_VER
#pragma runtime_checks("", off)
#endif
PrimaryKey Changeset::get_key(const Instruction::PrimaryKey& key) const noexcept
{
    const auto& get = overload{
        [this](InternString str) -> PrimaryKey {
            return get_string(str);
        },
        [](auto otherwise) -> PrimaryKey {
            return otherwise;
        },
    };
    return mpark::visit(get, key);
}
#if _MSC_VER
#pragma runtime_checks("", off)
#endif

bool Changeset::operator==(const Changeset& that) const noexcept
{
    if (m_instructions == that.m_instructions) {
        return *m_strings == *that.m_strings;
    }
    return false;
}

std::ostream& Changeset::print_value(std::ostream& os, const Instruction::Payload& value) const noexcept
{
    using Type = Instruction::Payload::Type;

    os << get_type_name(value.type) << "(";
    auto& data = value.data;
    switch (value.type) {
        case Type::ObjectValue:
            break;
        case Type::GlobalKey:
            os << data.key;
            break;
        case Type::Erased:
{'fraction_non_alphanumeric': 0.13145701046850866, 'fraction_numerical': 0.00789428522395744, 'mean_word_length': 3.8445552784704904, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6512577', 'n_tokens_mistral': 1912, 'n_tokens_neox': 1857, 'n_words': 379}