Repository: microsoft/terminal
File: src/buffer/out/UTextAdapter.cpp (C++)

Code before:
    til::CoordType begin;
    til::CoordType end;
};

constexpr size_t& accessLength(UText* ut) noexcept
{
    return *std::bit_cast<size_t*>(&ut->p);
}

constexpr RowRange& accessRowRange(UText* ut) noexcept
{
    return *std::bit_cast<RowRange*>(&ut->a);
}

constexpr til::CoordType& accessCurrentRow(UText* ut) noexcept
{
    return ut->b;
}

// An excerpt from the ICU documentation:
//
// Clone a UText. Much like opening a UText where the source text is itself another UText.
//
// A shallow clone replicates only the UText data structures; it does not make
// a copy of the underlying text. Shallow clones can be used as an efficient way to
// have multiple iterators active in a single text string that is not being modified.
//
// A shallow clone operation must not fail except for truly exceptional conditions such
// as memory allocation failures.
//
// @param dest   A UText struct to be filled in with the result of the clone operation,
//               or NULL if the clone function should heap-allocate a new UText struct.
// @param src    The UText to be cloned.
// @param deep   true to request a deep clone, false for a shallow clone.
// @param status Errors are returned here.  For deep clones, U_UNSUPPORTED_ERROR should
//               be returned if the text provider is unable to clone the original text.
// @return       The newly created clone, or NULL if the clone operation failed.
static UText* U_CALLCONV utextClone(UText* dest, const UText* src, UBool deep, UErrorCode* status) noexcept
{
    __assume(status != nullptr);

    if (deep)
    {
        *status = U_UNSUPPORTED_ERROR;
        return dest;
    }

    dest = utext_setup(dest, 0, status);
    if (*status <= U_ZERO_ERROR)
    {
        memcpy(dest, src, sizeof(UText));

Review comment (suggestion):
if we had to make a new buffer, make the new buffer's size the bigger of (2x the old buffer's size OR `capacity+128`). I guess to add some padding, in case the caller only needed `80` right now, but might want `200` with this same buffer

Code after:
#pragma warning(disable : 26402) // Return a scoped object instead of a heap-allocated if it has a move constructor (r.3).
#pragma warning(disable : 26403) // Reset or explicitly delete an owner<T> pointer '...' (r.3).
#pragma warning(disable : 26409) // Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11).

struct RowRange
{
    til::CoordType begin;
    til::CoordType end;
};

struct RefcountBuffer
{
    size_t references;
    size_t capacity;
    wchar_t data[1];

    static RefcountBuffer* EnsureCapacityForOverwrite(RefcountBuffer* buffer, size_t capacity)
    {
        // We must not just ensure that `buffer` has at least `capacity`, but also that its reference count is <= 1, because otherwise we would resize a shared buffer.
        if (buffer != nullptr && buffer->references <= 1 && buffer->capacity >= capacity)
        {
            return buffer;
        }

        const auto oldCapacity = buffer ? buffer->capacity << 1 : 0;
        const auto newCapacity = std::max(capacity + 128, oldCapacity);
        const auto newBuffer = static_cast<RefcountBuffer*>(::operator new(sizeof(RefcountBuffer) - sizeof(data) + newCapacity * sizeof(wchar_t)));

        if (!newBuffer)
        {
            return nullptr;
        }

        if (buffer)
        {
            buffer->Release();
        }

        // Copying the old buffer's data is not necessary because utextAccess() will scribble right over it.
        newBuffer->references = 1;
        newBuffer->capacity = newCapacity;
        return newBuffer;
    }

    void AddRef() noexcept
    {
        // With our usage patterns, either of these two would indicate
        // an unbalanced AddRef/Release or a memory corruption.
        assert(references > 0 && references < 1000);
        references++;
    }