#pragma once /**************************************************************************** Copyright (c) 2006, Radon Labs GmbH Copyright (c) 2011-2013,WebJet Business Division,CYOU http://www.genesis-3d.com.cn Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "core/types.h" #include "util/array.h" //------------------------------------------------------------------------------ namespace Util { template class FixedArray { public: /// define element iterator typedef TYPE* Iterator; /// default constructor FixedArray(); /// constructor with size FixedArray(SizeT s); /// constructor with size and initial value FixedArray(SizeT s, const TYPE& initialValue); /// copy constructor FixedArray(const FixedArray& rhs); /// destructor ~FixedArray(); /// assignment operator void operator=(const FixedArray& rhs); /// write [] operator TYPE& operator[](IndexT index) const; /// equality operator bool operator==(const FixedArray& rhs) const; /// inequality operator bool operator!=(const FixedArray& rhs) const; /// set number of elements (clears existing content) void SetSize(SizeT s); /// get number of elements SizeT Size() const; /// resize array without deleting existing content void Resize(SizeT newSize); /// return true if array if empty (has no elements) bool IsEmpty() const; /// clear the array, free elements void Clear(); /// fill the entire array with a value void Fill(const TYPE& val); /// fill array range with element void Fill(IndexT first, SizeT num, const TYPE& val); /// get iterator to first element Iterator Begin() const; /// get iterator past last element Iterator End() const; /// find identical element in unsorted array (slow) Iterator Find(const TYPE& val) const; /// find index of identical element in unsorted array (slow) IndexT FindIndex(const TYPE& val) const; /// sort the array void Sort(); /// do a binary search, requires a sorted array IndexT BinarySearchIndex(const TYPE& val) const; /// return content as Array (slow!) Array AsArray() const; private: /// delete content void Delete(); /// allocate array for given size void Alloc(SizeT s); /// copy content void Copy(const FixedArray& src); SizeT size; TYPE* elements; }; //------------------------------------------------------------------------------ /** */ template FixedArray::FixedArray() : size(0), elements(0) { // empty } //------------------------------------------------------------------------------ /** */ template void FixedArray::Delete() { if (this->elements) { n_delete_array(this->elements); this->elements = 0; } this->size = 0; } //------------------------------------------------------------------------------ /** */ template void FixedArray::Alloc(SizeT s) { #if NEBULA3_BOUNDSCHECKS n_assert(0 == this->elements) #endif if (s > 0) { this->elements = n_new_array(TYPE, s); } this->size = s; } //------------------------------------------------------------------------------ /** NOTE: only works on deleted array. This is intended. */ template void FixedArray::Copy(const FixedArray& rhs) { if (this != &rhs) { this->Alloc(rhs.size); IndexT i; for (i = 0; i < this->size; i++) { this->elements[i] = rhs.elements[i]; } } } //------------------------------------------------------------------------------ /** */ template FixedArray::FixedArray(SizeT s) : size(0), elements(0) { this->Alloc(s); } //------------------------------------------------------------------------------ /** */ template FixedArray::FixedArray(SizeT s, const TYPE& initialValue) : size(0), elements(0) { this->Alloc(s); this->Fill(initialValue); } //------------------------------------------------------------------------------ /** */ template FixedArray::FixedArray(const FixedArray& rhs) : size(0), elements(0) { this->Copy(rhs); } //------------------------------------------------------------------------------ /** */ template FixedArray::~FixedArray() { this->Delete(); } //------------------------------------------------------------------------------ /** */ template void FixedArray::operator=(const FixedArray& rhs) { this->Delete(); this->Copy(rhs); } //------------------------------------------------------------------------------ /** */ template TYPE& FixedArray::operator[](IndexT index) const { #if NEBULA3_BOUNDSCHECKS n_assert(this->elements && (index < this->size)); #endif return this->elements[index]; } //------------------------------------------------------------------------------ /** */ template bool FixedArray::operator==(const FixedArray& rhs) const { if (this->size != rhs.size) { return false; } else { #if NEBULA3_BOUNDSCHECKS n_assert(this->elements && rhs.elements); #endif IndexT i; SizeT num = this->size; for (i = 0; i < num; i++) { if (this->elements[i] != rhs.elements[i]) { return false; } } return true; } } //------------------------------------------------------------------------------ /** */ template bool FixedArray::operator!=(const FixedArray& rhs) const { return !(*this == rhs); } //------------------------------------------------------------------------------ /** */ template void FixedArray::SetSize(SizeT s) { this->Delete(); this->Alloc(s); } //------------------------------------------------------------------------------ /** */ template void FixedArray::Resize(SizeT newSize) { // allocate new array and copy over old elements TYPE* newElements = 0; if (newSize > 0) { newElements = n_new_array(TYPE, newSize); SizeT numCopy = this->size; if (numCopy > newSize) numCopy = newSize; IndexT i; for (i = 0; i < numCopy; i++) { newElements[i] = this->elements[i]; } } // delete old elements this->Delete(); // set content to new elements this->elements = newElements; this->size = newSize; } //------------------------------------------------------------------------------ /** */ template SizeT FixedArray::Size() const { return this->size; } //------------------------------------------------------------------------------ /** */ template bool FixedArray::IsEmpty() const { return 0 == this->size; } //------------------------------------------------------------------------------ /** */ template void FixedArray::Clear() { this->Delete(); } //------------------------------------------------------------------------------ /** */ template void FixedArray::Fill(const TYPE& val) { IndexT i; for (i = 0; i < this->size; i++) { this->elements[i] = val; } } //------------------------------------------------------------------------------ /** */ template void FixedArray::Fill(IndexT first, SizeT num, const TYPE& val) { #if NEBULA3_BOUNDSCHECKS n_assert((first + num) < this->size); n_assert(0 != this->elements); #endif IndexT i; for (i = first; i < (first + num); i++) { this->elements[i] = val; } } //------------------------------------------------------------------------------ /** */ template typename FixedArray::Iterator FixedArray::Begin() const { return this->elements; } //------------------------------------------------------------------------------ /** */ template typename FixedArray::Iterator FixedArray::End() const { return this->elements + this->size; } //------------------------------------------------------------------------------ /** */ template typename FixedArray::Iterator FixedArray::Find(const TYPE& elm) const { IndexT i; for (i = 0; i < this->size; i++) { if (elm == this->elements[i]) { return &(this->elements[i]); } } return 0; } //------------------------------------------------------------------------------ /** */ template IndexT FixedArray::FindIndex(const TYPE& elm) const { IndexT i; for (i = 0; i < this->size; i++) { if (elm == this->elements[i]) { return i; } } return InvalidIndex; } //------------------------------------------------------------------------------ /** */ template void FixedArray::Sort() { std::sort(this->Begin(), this->End()); } //------------------------------------------------------------------------------ /** @todo hmm, this is copy-pasted from Array... */ template IndexT FixedArray::BinarySearchIndex(const TYPE& elm) const { SizeT num = this->Size(); if (num > 0) { IndexT half; IndexT lo = 0; IndexT hi = num - 1; IndexT mid; while (lo <= hi) { if (0 != (half = num/2)) { mid = lo + ((num & 1) ? half : (half - 1)); if (elm < this->elements[mid]) { hi = mid - 1; num = num & 1 ? half : half - 1; } else if (elm > this->elements[mid]) { lo = mid + 1; num = half; } else { return mid; } } else if (num) { if (elm != this->elements[lo]) { return InvalidIndex; } else { return lo; } } else { break; } } } return InvalidIndex; } //------------------------------------------------------------------------------ /** */ template Array FixedArray::AsArray() const { Array result; result.Reserve(this->size); IndexT i; for (i = 0; i < this->size; i++) { result.Append(this->elements[i]); } return result; } } // namespace Util //------------------------------------------------------------------------------