#pragma once #include "memory_traits.h" namespace NAccessors { namespace NPrivate { template struct TMemoryAccessorBase { enum { SimpleMemory = TMemoryTraits::SimpleMemory, ContinuousMemory = TMemoryTraits::ContinuousMemory, }; struct TBadAccessor; }; template struct TBegin: public TMemoryAccessorBase { using TElementType = typename TMemoryTraits::TElementType; template struct TNoMemoryIndirectionBegin { static const TElementType* Get(const Tb& b) { return (const TElementType*)&b; } }; template struct TIndirectMemoryRegionBegin { Y_HAS_MEMBER(Begin); Y_HAS_MEMBER(begin); template struct TByBegin { static const TElementType* Get(const Tc& b) { return (const TElementType*)b.Begin(); } }; template struct TBybegin { static const TElementType* Get(const Tc& b) { return (const TElementType*)b.begin(); } }; using TGet = std::conditional_t::value, TByBegin, TBybegin>; static const TElementType* Get(const Tb& b) { return TGet::Get(b); } }; using TGet = std::conditional_t< TMemoryAccessorBase::SimpleMemory, TNoMemoryIndirectionBegin, std::conditional_t< TMemoryAccessorBase::ContinuousMemory, TIndirectMemoryRegionBegin, typename TMemoryAccessorBase::TBadAccessor>>; static const TElementType* Get(const Ta& b) { return TGet::Get(b); } }; template struct TEnd: public TMemoryAccessorBase { using TElementType = typename TMemoryTraits::TElementType; template struct TNoMemoryIndirectionEnd { static const TElementType* Get(const Tb& b) { return (const TElementType*)(&b + 1); } }; template struct TIndirectMemoryRegionEnd { Y_HAS_MEMBER(End); Y_HAS_MEMBER(end); template struct TByEnd { static const TElementType* Get(const Tc& b) { return (const TElementType*)b.End(); } }; template struct TByend { static const TElementType* Get(const Tc& b) { return (const TElementType*)b.end(); } }; using TGet = std::conditional_t::value, TByEnd, TByend>; static const TElementType* Get(const Tb& b) { return TGet::Get(b); } }; using TGet = std::conditional_t< TMemoryAccessorBase::SimpleMemory, TNoMemoryIndirectionEnd, std::conditional_t< TMemoryAccessorBase::ContinuousMemory, TIndirectMemoryRegionEnd, typename TMemoryAccessorBase::TBadAccessor>>; static const TElementType* Get(const Ta& b) { return TGet::Get(b); } }; template struct TClear: public TMemoryAccessorBase { template struct TNoMemoryIndirectionClear { static void Do(Tb& b) { Zero(b); } }; template struct TIndirectMemoryRegionClear { Y_HAS_MEMBER(Clear); Y_HAS_MEMBER(clear); template struct TByClear { static void Do(Tc& b) { b.Clear(); } }; template struct TByclear { static void Do(Tc& b) { b.clear(); } }; template struct TByNone { static void Do(Tc& b) { if (!Init) b = Tc(); } }; using TDo = std::conditional_t< THasClear::value, TByClear, std::conditional_t< THasclear::value, TByclear, TByNone>>; static void Do(Tb& b) { TDo::Do(b); } }; using TDo = std::conditional_t::SimpleMemory, TNoMemoryIndirectionClear, TIndirectMemoryRegionClear>; static void Do(Ta& b) { TDo::Do(b); } }; template struct TReserve { Y_HAS_MEMBER(Reserve); Y_HAS_MEMBER(reserve); template struct TByReserve { static void Do(Tc& b, size_t sz) { b.Reserve(sz); } }; template struct TByreserve { static void Do(Tc& b, size_t sz) { b.reserve(sz); } }; template struct TByNone { static void Do(Tc&, size_t) { } }; using TDo = std::conditional_t< THasReserve::value, TByReserve, std::conditional_t< THasreserve::value, TByreserve, TByNone>>; static void Do(Tb& b, size_t sz) { TDo::Do(b, sz); } }; template struct TResize { Y_HAS_MEMBER(Resize); Y_HAS_MEMBER(resize); template struct TByResize { static void Do(Tc& b, size_t sz) { b.Resize(sz); } }; template struct TByresize { static void Do(Tc& b, size_t sz) { b.resize(sz); } }; using TDo = std::conditional_t::value, TByResize, TByresize>; static void Do(Tb& b, size_t sz) { TDo::Do(b, sz); } }; template struct TAppend { Y_HAS_MEMBER(Append); Y_HAS_MEMBER(append); Y_HAS_MEMBER(push_back); template struct TByAppend { using TElementType = typename TMemoryTraits::TElementType; static void Do(Tc& b, const TElementType& val) { b.Append(val); } }; template struct TByappend { using TElementType = typename TMemoryTraits::TElementType; static void Do(Tc& b, const TElementType& val) { b.append(val); } }; template struct TBypush_back { using TElementType = typename TMemoryTraits::TElementType; static void Do(Tc& b, const TElementType& val) { b.push_back(val); } }; using TDo = std::conditional_t< THasAppend::value, TByAppend, std::conditional_t< THasappend::value, TByappend, TBypush_back>>; using TElementType = typename TMemoryTraits::TElementType; static void Do(Tb& b, const TElementType& val) { TDo::Do(b, val); } }; template struct TAppendRegion { Y_HAS_MEMBER(Append); Y_HAS_MEMBER(append); Y_HAS_MEMBER(insert); template struct TByAppend { using TElementType = typename TMemoryTraits::TElementType; static void Do(Tc& b, const TElementType* beg, const TElementType* end) { b.Append(beg, end); } }; template struct TByappend { using TElementType = typename TMemoryTraits::TElementType; static void Do(Tc& b, const TElementType* beg, const TElementType* end) { b.append(beg, end); } }; template struct TByinsert { using TElementType = typename TMemoryTraits::TElementType; static void Do(Tc& b, const TElementType* beg, const TElementType* end) { b.insert(b.end(), beg, end); } }; template struct TByNone { using TElementType = typename TMemoryTraits::TElementType; static void Do(Tc& b, const TElementType* beg, const TElementType* end) { for (const TElementType* it = beg; it != end; ++it) TAppend::Do(b, *it); } }; using TDo = std::conditional_t< THasAppend::value, TByAppend, std::conditional_t< THasappend::value, TByappend, std::conditional_t< THasinsert::value, TByinsert, TByNone>>>; using TElementType = typename TMemoryTraits::TElementType; static void Do(Tb& b, const TElementType* beg, const TElementType* end) { TDo::Do(b, beg, end); } }; template struct TAssign: public TMemoryAccessorBase { using TElementType = typename TMemoryTraits::TElementType; template struct TNoMemoryIndirectionAssign { static void Do(Tb& b, const TElementType* beg, const TElementType* end) { if (sizeof(Tb) == sizeof(TElementType) && end - beg > 0) { memcpy(&b, beg, sizeof(Tb)); } else if (end - beg > 0) { memcpy(&b, beg, Min((end - beg) * sizeof(TElementType), sizeof(Tb))); } else { Zero(b); } } }; template struct TIndirectMemoryRegionAssign { Y_HAS_MEMBER(Assign); Y_HAS_MEMBER(assign); template struct TByAssign { static void Do(Tc& b, const TElementType* beg, const TElementType* end) { b.Assign(beg, end); } }; template struct TByassign { static void Do(Tc& b, const TElementType* beg, const TElementType* end) { b.assign(beg, end); } }; template struct TByClearAppend { static void Do(Tc& b, const TElementType* beg, const TElementType* end) { TClear::Do(b); TAppendRegion::Do(b, beg, end); } }; template struct TByConstruction { static void Do(Tc& b, const TElementType* beg, const TElementType* end) { b = Tc(beg, end); } }; using TDo = std::conditional_t< THasAssign::value, TByAssign, std::conditional_t< THasassign::value, TByassign, std::conditional_t< TMemoryTraits::OwnsMemory, TByClearAppend, TByConstruction>>>; static void Do(Tb& b, const TElementType* beg, const TElementType* end) { TDo::Do(b, beg, end); } }; using TDo = std::conditional_t::SimpleMemory, TNoMemoryIndirectionAssign, TIndirectMemoryRegionAssign>; static void Do(Ta& b, const TElementType* beg, const TElementType* end) { TDo::Do(b, beg, end); } }; } }