git » swiftpm » main » tree

[main] / Sources / c_borogove / iinclude / cpp / marshal / View.hpp

#pragma once

#include "Definitions.inc"
#include <cstring>
#include <cmath>

template<class T>
inline cpp::marshal::View<T>::View(::cpp::Pointer<T> _ptr, int64_t _length) : ptr(_ptr), length(_length) {}

template<class T>
inline bool cpp::marshal::View<T>::tryCopyTo(const View<T>& destination) const
{
    if (destination.length < length)
    {
        return false;
    }

    if (ptr.ptr + length < destination.ptr.ptr || destination.ptr.ptr + length < ptr.ptr)
        std::memcpy(destination.ptr.ptr, ptr.ptr, sizeof(T) * length);
    else
        std::memmove(destination.ptr.ptr, ptr.ptr, sizeof(T) * length);

    return true;
}

template<class T>
inline void cpp::marshal::View<T>::copyTo(const View<T>& destination) const
{
    if (tryCopyTo(destination) == false)
    {
        hx::Throw(HX_CSTRING("View OOB"));
    }
}

template<class T>
inline void cpp::marshal::View<T>::clear() const
{
    std::memset(ptr.ptr, 0, sizeof(T) * length);
}

template<class T>
inline void cpp::marshal::View<T>::fill(T value) const
{
    for (auto i = 0; i < length; i++)
    {
        ptr.ptr[i] = value;
    }
}

template<class T>
inline bool cpp::marshal::View<T>::isEmpty() const
{
    return length == 0;
}

template<class T>
inline cpp::marshal::View<T> cpp::marshal::View<T>::slice(int64_t index) const
{
    if (index < 0 || index > length)
    {
        hx::Throw(HX_CSTRING("View OOB"));
    }

    return View<T>(ptr.ptr + index, length - index);
}

template<class T>
inline cpp::marshal::View<T> cpp::marshal::View<T>::slice(int64_t inIndex, int64_t inLength) const
{
    if (inIndex < 0 || inLength < 0 || inIndex > length || inIndex + inLength > length)
    {
        hx::Throw(HX_CSTRING("View OOB"));
    }

    return View<T>(ptr.ptr + inIndex, inLength);
}

template<class T>
template<class K>
inline cpp::marshal::View<K> cpp::marshal::View<T>::reinterpret() const
{
    auto newPtr   = ::cpp::Pointer<K>(reinterpret_cast<K*>(ptr.ptr));
    auto fromSize = sizeof(T);
    auto toSize   = sizeof(K);

    if (toSize == fromSize)
    {
        return cpp::marshal::View<K>(newPtr, length);
    }
    if (toSize < fromSize)
    {
        return cpp::marshal::View<K>(newPtr, length * (fromSize / toSize));
    }

    auto shrink    = static_cast<double>(fromSize) / toSize;
    auto newLength = static_cast<int>(std::floor(length * shrink));

    return cpp::marshal::View<K>(newPtr, newLength);
}

template<class T>
inline int cpp::marshal::View<T>::compare(const View<T>& inRHS) const
{
    auto common = length < inRHS.length ? length : inRHS.length;
    auto result = std::memcmp(ptr.ptr, inRHS.ptr.ptr, sizeof(T) * common);

    if (result)
    {
        return result;
    }

    return length - inRHS.length;
}

template<class T>
inline bool cpp::marshal::View<T>::operator==(const View<T>& inRHS) const
{
    return length == inRHS.length && ptr.ptr == inRHS.ptr.ptr;
}

template<class T>
inline bool cpp::marshal::View<T>::operator!=(const View<T>& inRHS) const
{
    return length != inRHS.length || ptr.ptr != inRHS.ptr.ptr;
}

template<class T>
inline T& cpp::marshal::View<T>::operator[](int64_t index) const
{
    if (index < 0 || index >= length)
    {
        hx::Throw(HX_CSTRING("View OOB"));
    }

    return ptr.ptr[index];
}