1 /*
2  *  Array.h
3  *  Apto
4  *
5  *  Created by David on 2/4/11.
6  *  Copyright 2011 David Michael Bryson. All rights reserved.
7  *  http://programerror.com/software/apto
8  *
9  *  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
10  *  following conditions are met:
11  *
12  *  1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the
13  *      following disclaimer.
14  *  2.  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
15  *      following disclaimer in the documentation and/or other materials provided with the distribution.
16  *  3.  Neither the name of David Michael Bryson, nor the names of contributors may be used to endorse or promote
17  *      products derived from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY DAVID MICHAEL BRYSON AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  *  DISCLAIMED. IN NO EVENT SHALL DAVID MICHAEL BRYSON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  *  Authors: David M. Bryson <david@programerror.com>
28  *
29  */
30 
31 #ifndef AptoCoreArray_h
32 #define AptoCoreArray_h
33 
34 #include "apto/core/Definitions.h"
35 #include "apto/core/ArrayStorage.h"
36 
37 #include <cassert>
38 
39 
40 namespace Apto {
41 
42   // Array
43   // --------------------------------------------------------------------------------------------------------------
44 
45   template <class T, template <class> class StoragePolicy = Basic>
46   class Array : public StoragePolicy<T>
47   {
48     typedef StoragePolicy<T> SP;
49 
50   public:
51     typedef T ValueType;
52     class Iterator;
53     class ConstIterator;
54 
55   public:
SP(size)56     inline explicit Array(int size = 0) : SP(size) { ; }
57 
58     template <typename T1, template <class> class SP1>
Array(const Array<T1,SP1> & rhs)59     inline explicit Array(const Array<T1, SP1>& rhs) : SP(rhs.GetSize()) { this->operator=(rhs); }
60 
~Array()61     ~Array() { ; }
62 
63     template <typename T1, template <class> class SP1>
64     Array& operator=(const Array<T1, SP1>& rhs)
65     {
66       if (SP::GetSize() != rhs.GetSize()) SP::Resize(rhs.GetSize());
67       for (int i = 0; i < GetSize(); i++) SP::operator[](i) = rhs[i];
68       return *this;
69     }
70 
71     template <typename T1, template <class> class SP1>
72     Array& operator+=(const Array<T1, SP1>& rhs)
73     {
74       int old_size = SP::GetSize();
75       int rhs_size = rhs.GetSize();
76       SP::Resize(old_size + rhs_size);
77       for (int i = 0; i < rhs_size; i++) SP::operator[](i + old_size) = rhs[i];
78       return *this;
79     }
80 
81     template <typename T1, template <class> class SP1>
82     Array operator+(const Array<T1, SP1>& rhs) const
83     {
84       Array new_arr(SP::GetSize() + rhs.GetSize());
85       for (int i = 0; i < SP::GetSize(); i++) new_arr[i] = SP::operator[](i);
86       for (int i = 0; i < rhs.GetSize(); i++) new_arr[SP::GetSize() + i] = rhs[i];
87       return new_arr;
88     }
89 
90     template <typename T1, template <class> class SP1>
91     bool operator==(const Array<T1, SP1>& rhs)
92     {
93       if (SP::GetSize() != rhs.GetSize()) return false;
94       for (int i = 0; i < SP::GetSize(); i++) if (SP::operator[](i) != rhs[i]) return false;
95       return true;
96     }
97 
98     template <typename T1, template <class> class SP1>
99     bool operator!=(const Array<T1, SP1>& rhs) { return !operator==(rhs); }
100 
GetSize()101     inline int GetSize() const { return SP::GetSize(); }
102 
ResizeClear(const int in_size)103     inline void ResizeClear(const int in_size)
104     {
105       assert(in_size >= 0);
106       SP::ResizeClear(in_size);
107     }
108 
Resize(int new_size)109     inline void Resize(int new_size)
110     {
111       assert(new_size >= 0);
112       SP::Resize(new_size);
113     }
114 
Resize(int new_size,const T & empty_value)115     void Resize(int new_size, const T& empty_value)
116     {
117       int old_size = SP::GetSize();
118       SP::Resize(new_size);
119       for (int i = old_size; i < new_size; i++) SP::operator[](i) = empty_value;
120     }
121 
122     T& operator[](const int index)
123     {
124       assert(index >= 0);       // Lower Bounds Error
125       assert(index < SP::GetSize()); // Upper Bounds Error
126       return SP::operator[](index);
127     }
128     const T& operator[](const int index) const
129     {
130       assert(index >= 0);       // Lower Bounds Error
131       assert(index < SP::GetSize()); // Upper Bounds Error
132       return SP::operator[](index);
133     }
134 
Get(const int index)135     inline T& Get(const int index) { return operator[](index); }
Get(const int index)136     inline const T& Get(const int index) const { return operator[](index); }
137 
138     // Stack-like Methods...
Push(const T & value)139     void Push(const T& value)
140     {
141       SP::Resize(SP::GetSize() + 1);
142       SP::operator[](SP::GetSize() - 1) = value;
143     }
144 
Pop()145     T Pop()
146     {
147       T value = SP::operator[](SP::GetSize() - 1);
148       SP::Resize(SP::GetSize() - 1);
149       return value;
150     }
151 
152 
Swap(int idx1,int idx2)153     void Swap(int idx1, int idx2)
154     {
155       assert(idx1 >= 0);      // Lower Bounds Error
156       assert(idx1 < SP::GetSize());  // Upper Bounds Error
157       assert(idx2 >= 0);      // Lower Bounds Error
158       assert(idx2 < SP::GetSize());  // Upper Bounds Error
159 
160       SP::Swap(idx1, idx2);
161     }
162 
163 
SetAll(const T & value)164     void SetAll(const T& value)
165     {
166       for (int i = 0; i < SP::GetSize(); i++) SP::operator[](i) = value;
167     }
168 
Begin()169     Iterator Begin() { return Iterator(*this); }
Begin()170     ConstIterator Begin() const { return ConstIterator(*this); }
171 
172 
173   public:
174     class Iterator
175     {
176       friend class Array;
177 
178     private:
179       Array& m_arr;
180       int m_index;
181 
182       Iterator(); // @not_implemented
Iterator(Array & arr)183       Iterator(Array& arr) : m_arr(arr), m_index(-1) { ; }
184 
185     public:
Get()186       T* Get() { return (m_index < m_arr.GetSize()) ? &(m_arr.SP::operator[](m_index)) : NULL; }
Next()187       T* Next() { return (++m_index < m_arr.GetSize()) ? &(m_arr.SP::operator[](m_index)) : NULL; }
188     };
189 
190     class ConstIterator
191     {
192       friend class Array;
193     private:
194       const Array& m_arr;
195       int m_index;
196 
197       ConstIterator(); // @not_implemented
ConstIterator(const Array & arr)198       ConstIterator(const Array& arr) : m_arr(arr), m_index(-1) { ; }
199 
200     public:
Get()201       const T* Get() { return (m_index < m_arr.GetSize()) ? &(m_arr.SP::operator[](m_index)) : NULL; }
Next()202       const T* Next() { return (++m_index < m_arr.GetSize()) ? &(m_arr.SP::operator[](m_index)) : NULL; }
203     };
204   };
205 };
206 
207 #endif
208