|
//**************************************************************************************************************************
//* Blue - General Purpose C++ Library
//* Copyright (c) 2002 Josh Harler
//*
//* This software is provided 'as-is', without any express or implied warranty. In no event
//* will the authors be held liable for any damages arising from the use of this software.
//*
//* Permission is granted to anyone to use this software for any purpose, including commercial
//* applications, and to alter it and redistribute it freely, subject to the following restrictions:
//*
//* 1. The origin of this software must not be misrepresented; you must not claim that you
//* wrote the original software. If you use this software in a product, an acknowledgment in the
//* product documentation would be appreciated but is not required.
//*
//* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as
//* being the original software.
//*
//* 3. This notice may not be removed or altered from any source distribution.
//*
//*
//* file Common/Array.h
//**
#ifndef __blue_common_Array_h_included__
#define __blue_common_Array_h_included__
// Public Headers ==========================================================================================================
// Public Defines/Enums/Typedefs/Etc. ======================================================================================
// Public Classes/Structs ==================================================================================================
namespace blue
{
namespace common
{
/**
* \class Array
* \brief Template array class.
* \ingroup Common
*/
template <typename type_t> class Array
{
public:
// ===========================================================
// creation/destruction
// ===========================================================
/** Constructor. */
Array() :m_refData(0), m_refSize(0), m_refCnt(0)
{}
/** Constructor. */
explicit Array(int size) :m_refData(0), m_refSize(0), m_refCnt(0)
{ refCreate(size); }
/** Copy constructor. */
Array(const Array < type_t>& copy) :m_refData(copy.m_refData), m_refSize(copy.m_refSize), m_refCnt(copy.m_refCnt)
{ refInc(); }
/** Destructor. */
~Array()
{
refDec();
}
// ===========================================================
// query
// ===========================================================
/** Returns the number of elements in the array. */
int getSize() const
{
return (m_refSize == 0 ? 0 : *m_refSize);
}
/** Determines if the array contains any elements. */
bool isEmpty() const
{
return (m_refData == 0);
}
/** Returns the element of the array at the given index. */
type_t& access(int index)
{
BLUE_ASSERT(index >= 0 && m_refData != 0 && index < *m_refSize);
return (m_refData[index]);
}
/** overload */
const type_t& access(int index) const
{
BLUE_ASSERT(index >= 0 && m_refData != 0 && index < *m_refSize);
return (m_refData[index]);
}
/** Returns a pointer to the first element of the array. */
type_t* accessData()
{
BLUE_ASSERT(m_refData != 0);
return (m_refData);
}
/** overload */
const type_t* accessData() const
{
BLUE_ASSERT(m_refData != 0);
return (m_refData);
}
/** Operator[] to access the items in the array. */
type_t& operator[](int index)
{
return access(index);
}
/** overload */
const type_t& operator[](int index) const
{
return access(index);
}
/** Determines if the two arrays point to the same data. */
bool operator==(const Array < type_t>& other)
{
return (m_refData == other.m_refData);
}
/** Determines if the two arrays do not point to the same data. */
bool operator!=(const Array < type_t>& other)
{
return (m_refData != other.m_refData);
}
// ===========================================================
// manipulation
// ===========================================================
/** Empties the array. */
void clear()
{
refDec();
}
/**
* Sets the size of the array. This removes all existing items from
* the array.
*/
void setSize(int size)
{
refCreate(size);
}
/**
* Similar to Array::setSize, but the items currently in the array
* are copied into the new array. This can be slow if the items in
* the array are stored by value.
*/
void resize(int size)
{
int minLen = (size < getSize() ? size : getSize());
Array < type_t> copy(size);
for (int i = 0; i < minLen; ++i)
{
copy[i] = access(i);
}
refCreate(copy);
}
/**
* Resizes the array by one element and adds the given item to the end.
*/
void append(const type_t& item)
{
Array < type_t> copy(getSize() + 1);
for (int i = 0; i < getSize(); ++i)
{
copy[i] = access(i);
}
copy[getSize()] = item;
refCreate(copy);
}
/**
* Resizes the array by the number of items in the given array and
* adds the given array items to the end of this array.
*/
void append(const Array < type_t>& array)
{
if (array.getSize() <= 0)
{
return;
}
int idx, cur = 0;;
Array < type_t> copy(getSize() + array.getSize());
for (idx = 0; idx < getSize(); ++idx)
{
copy[cur++] = access(idx);
}
for (idx = 0; idx < array.getSize(); ++idx)
{
copy[cur++] = array.access(idx);
}
refCreate(copy);
}
/**
* Resizes the array by one element and inserts the given item before
* the index given.
*/
void insert(const type_t& item, int before)
{
BLUE_ASSERT((before > 0 && m_refData != 0 && before <= *m_refSize) || before == 0);
int idx, cur = 0;
Array < type_t> copy(getSize() + 1);
for (idx = 0; idx < before; ++idx)
{
copy[cur++] = access(idx);
}
copy[cur++] = item;
for (idx = before; idx < getSize(); ++idx)
{
copy[cur++] = access(idx);
}
refCreate(copy);
}
/**
* Resizes the array by one element, and removes the given item from
* the array.
*/
void remove(int index)
{
BLUE_ASSERT(index >= 0 && m_refData != 0 && index < *m_refSize);
int idx, cur = 0;
Array < type_t> copy(getSize() - 1);
for (idx = 0; idx < getSize(); ++idx)
{
if (idx != index)
{
copy[cur++] = access(idx);
}
}
refCreate(copy);
}
/**
* Returns a new array that contains the same items as this one.
*/
Array < type_t> copy() const
{
Array < type_t> clone(getSize());
for (int i = 0; i < getSize(); ++i)
{
clone[i] = access(i);
}
return (clone);
}
/**
* Assignment operator. References an existing %Array. Both arrays
* will see changes made to either one of them.
*/
Array<type_t>& operator=(const Array < type_t>& other)
{
if (&other == this)
{
return (*this);
}
refDec();
m_refData = other.m_refData;
m_refSize = other.m_refSize;
m_refCnt = other.m_refCnt;
refInc();
return (*this);
}
/**
* Appending operator.
*/
Array<type_t>& operator+=(const Array < type_t>& other)
{
append(other);
return (*this);
}
/**
* Concatinating operator. Merges the two arrays into one.
*/
Array<type_t> operator+(const Array < type_t>& other)
{
Array < type_t> clone(copy());
clone += other;
return (clone);
}
private:
void refInc()
{
if (m_refCnt != 0)
{
++*m_refCnt;
}
}
void refDec()
{
if (m_refCnt != 0)
{
if (--*m_refCnt == 0)
{
delete m_refCnt;
if (m_refSize)
{
delete m_refSize;
}
if (m_refData)
{
delete[] m_refData;
}
}
}
m_refCnt = 0;
m_refData = 0;
m_refSize = 0;
}
void refCreate(int size)
{
refDec();
if (size <= 0)
{
return;
}
m_refCnt = new int;
m_refSize = new int;
m_refData = new type_t[size];
*m_refCnt = 1;
*m_refSize = size;
}
void refCreate(Array < type_t>& copy)
{
if (copy.m_refCnt == 0)
{
refDec();
}
else
{
if (m_refCnt == 0)
{
m_refCnt = new int;
*m_refCnt = 1;
}
swap(m_refData, copy.m_refData);
swap(m_refSize, copy.m_refSize);
}
}
int* m_refCnt;
int* m_refSize;
type_t* m_refData;
};
}
} // namespaces
// Public External Variables ===============================================================================================
// Public Function Prototypes ==============================================================================================
// Public Inline Functions =================================================================================================
#endif // include guard
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.