1 //----------------------------------------------------------------------------
2 //  EDGE Array Class
3 //----------------------------------------------------------------------------
4 //
5 //  Copyright (c) 2002-2008  The EDGE Team.
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; either version 2
10 //  of the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //----------------------------------------------------------------------------
18 #ifndef __EPI_ARRAY_CLASS__
19 #define __EPI_ARRAY_CLASS__
20 
21 #ifndef NULL
22 #define NULL ((void*)0)
23 #endif
24 
25 namespace epi
26 {
27 	// Forward declarations
28 	class array_c;
29 	class array_iterator_c;
30 
31 	// Typedefs
32 	typedef int array_block_t;
33 
34 	// Classes
35 
36 	// The array
37 	class array_c
38 	{
39 		friend class array_iterator_c;
40 
41 	public:
42 		array_c(const int objsize);
43 		virtual ~array_c();
44 
45 	protected:
46 		unsigned int array_block_objsize;
47 		unsigned int array_objsize;
48 
49 		array_block_t *array;
50 		array_block_t *array_end;
51 		int array_entries;
52 		int array_max_entries;
53 
54 		void* ExpandAtTail(void);
55 
FetchObjectDirect(int pos)56 		void* FetchObjectDirect(int pos) const
57 			{ return (void*)&array[pos*array_block_objsize]; }
58 
59 		void ShrinkAtTail(void);
60 
61 		// Count management
DecrementCount()62 		void DecrementCount()
63 		{
64 			array_entries--;
65 			array_end -= array_block_objsize;
66 		}
67 
IncrementCount()68 		void IncrementCount()
69 		{
70 			array_entries++;
71 			array_end += array_block_objsize;
72 		}
73 
SetCount(int count)74 		void SetCount(int count)
75 		{
76 			array_entries = count;
77 			array_end = array + (array_block_objsize*array_entries);
78 		}
79 
80 	public:
81 		// Object Management
82 		virtual void CleanupObject(void *obj) = 0;
83 		void* FetchObject(int pos) const;
84 		int InsertObject(void *obj, int pos = -1);
85 		void RemoveObject(int pos);
86 
87 		// Iterator handling
88 		array_iterator_c GetBaseIterator();
89 		array_iterator_c GetIterator(int pos);
90 		array_iterator_c GetTailIterator();
91 
92 		// List Management
93 		void Clear(void);
94 		bool Size(int entries);
95 		bool Trim(void);
ZeroiseCount(void)96 		void ZeroiseCount(void) { array_end = array; array_entries = 0; }
97 	};
98 
99 
100 	// The array iterator
101 	class array_iterator_c
102 	{
103 	public:
array_iterator_c()104 		array_iterator_c()
105 		{
106 			parent = (epi::array_c*)NULL;
107 			idx = 0;
108 		}
109 
array_iterator_c(array_c * ptr,int initpos)110 		array_iterator_c(array_c *ptr, int initpos)
111 		{
112 			parent = ptr;
113 			idx = initpos*parent->array_block_objsize;
114 		}
115 
~array_iterator_c()116 		~array_iterator_c()
117 		{
118 		}
119 
120 	private:
121 		array_c* parent;
122 		int idx;
123 
124 	public:
GetPos()125 		int GetPos() { return idx ? idx/parent->array_block_objsize : 0; }
126 
IsValid()127 		bool IsValid()
128 		{
129 			return ((parent->array + idx) >= parent->array_end)?false:true;
130 		}
131 
SetPos(int pos)132 		void SetPos(int pos) { idx = pos * parent->array_block_objsize; }
133 
134 		operator void* () const
135 		{
136 			return (void*)((array_block_t*)(parent->array + idx));
137 		}
138 
139 		void operator++(int)
140 		{
141 			idx += parent->array_block_objsize;
142 		}
143 
144 		void operator--(int)
145 		{
146 			if (idx)
147 				idx -= parent->array_block_objsize;
148 			else
149 				idx = parent->array_entries*parent->array_block_objsize; // Max out to make invalid
150 		}
151 	};
152 };
153 
154 // Helper defines
155 #define BEGIN_IMPLEMENT_ARRAY(_type, _name) \
156 	class _name : public epi::array_c \
157 	{\
158 	public:\
159 		_name() : epi::array_c(sizeof(_type)) {}\
160 		~_name() { Clear(); } \
161 		\
162 		int GetSize() const { return array_entries; } \
163 		_type* operator[](int idx) { return (_type*)FetchObject(idx); }
164 
165 #define END_IMPLEMENT_ARRAY \
166 	}
167 
168 #define IMPLEMENT_PRIMITIVE_ARRAY(_type, _name) \
169 	BEGIN_IMPLEMENT_ARRAY(_type, _name) \
170 		private: void CleanupObject(void *obj) { /* Do Nothing */ } \
171 		public: int Insert(_type p) { return InsertObject((void*)&p); } \
172 	END_IMPLEMENT_ARRAY
173 
174 #define ITERATOR_TO_PTR(_it, _type) \
175 	((_type*)((void*)(_it)))
176 
177 #define ITERATOR_TO_TYPE(_it, _type) \
178 	(*(_type*)((void*)(_it)))
179 
180 #endif /* __EPI_ARRAY_CLASS__ */
181 
182 //--- editor settings ---
183 // vi:ts=4:sw=4:noexpandtab
184