// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // -------------------------------------------------------------------------------- // SArray.inl // -------------------------------------------------------------------------------- #ifndef _SARRAY_INL_ #define _SARRAY_INL_ #include "sarray.h" template inline SArray::SArray() : m_buffer() { LIMITED_METHOD_CONTRACT; } template inline SArray::SArray(COUNT_T count) : m_buffer(count * sizeof(ELEMENT)) { WRAPPER_NO_CONTRACT; ConstructBuffer(Begin(), count); } template inline COUNT_T SArray::VerifySizeRange(ELEMENT * begin, ELEMENT *end) { WRAPPER_NO_CONTRACT; if (end < begin) ThrowHR(COR_E_OVERFLOW); SIZE_T bufferSize = (end - begin) * sizeof(ELEMENT); if (!FitsIn(bufferSize)) ThrowHR(COR_E_OVERFLOW); return static_cast(bufferSize); } template inline SArray::SArray(ELEMENT * begin, ELEMENT * end) : m_buffer(VerifySizeRange(begin, end)) { WRAPPER_NO_CONTRACT; CopyConstructBuffer(Begin(), static_cast(end - begin), begin); } template inline SArray::SArray(void *prealloc, COUNT_T count) : m_buffer(SBuffer::Prealloc, prealloc, count*sizeof(ELEMENT)) { LIMITED_METHOD_CONTRACT; } template SArray::~SArray() { CONTRACTL { NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; // Cannot call Clear because DestructBuffer has THROWS in its contract if (!BITWISE_COPY) { COUNT_T elementCount = GetCount(); for (COUNT_T i = 0; i < elementCount; i++) { (&((*this)[i]))->~ELEMENT(); } } } template inline void SArray::Clear() { WRAPPER_NO_CONTRACT; DestructBuffer(Begin(), GetCount()); m_buffer.Clear(); } template inline ELEMENT* SArray::OpenRawBuffer(COUNT_T elementCount) { WRAPPER_NO_CONTRACT; return (ELEMENT*)m_buffer.OpenRawBuffer(elementCount * sizeof(ELEMENT)); } template inline ELEMENT* SArray::OpenRawBuffer() { WRAPPER_NO_CONTRACT; return (ELEMENT*)m_buffer.OpenRawBuffer(GetCount() * sizeof(ELEMENT)); } template inline void SArray::CloseRawBuffer(COUNT_T finalElementCount) { WRAPPER_NO_CONTRACT; m_buffer.CloseRawBuffer(finalElementCount * sizeof(ELEMENT)); } template inline void SArray::CloseRawBuffer() { WRAPPER_NO_CONTRACT; m_buffer.CloseRawBuffer(); } template inline void SArray::Set(const SArray &array) { WRAPPER_NO_CONTRACT; if (BITWISE_COPY) { m_buffer.Set(array.m_buffer); } else { DestructBuffer(Begin(), GetCount()); m_buffer.SetSize(0); m_buffer.SetSize(array.m_buffer.GetSize()); CopyConstructBuffer(Begin(), GetCount(), array.GetElements()); } } template inline COUNT_T SArray::GetCount() const { WRAPPER_NO_CONTRACT; return m_buffer.GetSize()/sizeof(ELEMENT); } template inline BOOL SArray::IsEmpty() const { WRAPPER_NO_CONTRACT; return GetCount() == 0; } template inline void SArray::SetCount(COUNT_T count) { WRAPPER_NO_CONTRACT; COUNT_T oldCount = GetCount(); if (count > oldCount) ConstructBuffer(Begin() + oldCount, count - oldCount); m_buffer.SetSize(count*sizeof(ELEMENT)); if (oldCount > count) DestructBuffer(Begin() + count, oldCount - count); } template inline COUNT_T SArray::GetAllocation() const { WRAPPER_NO_CONTRACT; return m_buffer.GetAllocation() / sizeof(ELEMENT); } template inline void SArray::Preallocate(int count) const { WRAPPER_NO_CONTRACT; m_buffer.Preallocate(count * sizeof(ELEMENT)); } template inline void SArray::Trim() const { WRAPPER_NO_CONTRACT; m_buffer.Trim(); } template inline void SArray::Copy(const Iterator &to, const Iterator &from, COUNT_T size) { WRAPPER_NO_CONTRACT; // @todo: destruction/construction semantics are broken on overlapping copies DestructBuffer(to, size); CopyConstructBuffer(to, size, from); } template inline void SArray::Move(const Iterator &to, const Iterator &from, COUNT_T size) { // @todo: destruction/construction semantics are broken on overlapping moves DestructBuffer(to, size); m_buffer.Move(to, from, size*sizeof(ELEMENT)); ConstructBuffer(from, size); } template inline void SArray::Copy(const Iterator &i, const ELEMENT *source, COUNT_T size) { WRAPPER_NO_CONTRACT; DestructBuffer(i, size); CopyConstructBuffer(i, size, source); } template inline void SArray::Copy(void *dest, const Iterator &i, COUNT_T size) { WRAPPER_NO_CONTRACT; // @todo: destruction/construction semantics are unclear m_buffer.Copy(dest, i.m_i, size*sizeof(ELEMENT)); } template inline void SArray::Insert(const Iterator &i) { WRAPPER_NO_CONTRACT; Replace(i, 0, 1); } template inline void SArray::Delete(const Iterator &i) { WRAPPER_NO_CONTRACT; Replace(i, 1, 0); } template inline void SArray::Insert(const Iterator &i, COUNT_T count) { WRAPPER_NO_CONTRACT; Replace(i, 0, count); } template inline void SArray::Delete(const Iterator &i, COUNT_T count) { Delete(i, 0, count); } template inline void SArray:: Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount) { WRAPPER_NO_CONTRACT; DestructBuffer(i, deleteCount); m_buffer.Replace(i.m_i, deleteCount*sizeof(ELEMENT), insertCount*sizeof(ELEMENT)); ConstructBuffer(i, insertCount); } template inline ELEMENT &SArray::operator[](int index) { WRAPPER_NO_CONTRACT; return *(GetElements() + index); } template inline const ELEMENT &SArray::operator[](int index) const { WRAPPER_NO_CONTRACT; return *(GetElements() + index); } template inline ELEMENT &SArray::operator[](COUNT_T index) { WRAPPER_NO_CONTRACT; return *(GetElements() + index); } template inline const ELEMENT &SArray::operator[](COUNT_T index) const { return *(GetElements() + index); } template inline ELEMENT *SArray::GetElements() const { LIMITED_METHOD_CONTRACT; return (ELEMENT *) (const BYTE *) m_buffer; } template inline void SArray::ConstructBuffer(const Iterator &i, COUNT_T size) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; if (!BITWISE_COPY) { ELEMENT *start = GetElements() + (i - Begin()); ELEMENT *end = start + size; while (start < end) { new (start) ELEMENT(); start++; } } } template inline void SArray::CopyConstructBuffer(const Iterator &i, COUNT_T size, const ELEMENT *from) { ptrdiff_t start_offset = i - Begin(); ELEMENT *p = (ELEMENT *) m_buffer.OpenRawBuffer(m_buffer.GetSize()) + start_offset; if (BITWISE_COPY) { memmove(p, from, size * sizeof(ELEMENT)); } else { ELEMENT *start = (ELEMENT *) p; ELEMENT *end = (ELEMENT *) (p + size); while (start < end) { new (start) ELEMENT(*from); start++; from++; } } m_buffer.CloseRawBuffer(); } template inline void SArray::DestructBuffer(const Iterator &i, COUNT_T size) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; if (!BITWISE_COPY) { ELEMENT *start = GetElements() + (i - Begin()); ELEMENT *end = start + size; while (start < end) { start->ELEMENT::~ELEMENT(); start++; } } } template inline InlineSArray::InlineSArray() : SArray((void*)m_prealloc, SIZE) { LIMITED_METHOD_CONTRACT; } #endif // _SARRAY_INL_