6 #include "cln/object.h"
8 #include "cln/exception.h"
14 // A vector is a structure having the following interface:
15 // v.size() returns the number of elements
16 // v[i] returns the i-th element (0<=i<length), as a
17 // pseudo-lvalue (you can assign to it, but not take its
18 // address - exactly what you want for bit-vectors)
19 // This is implemented by letting v[i] be of a special "vector index" type.
21 template <class T> class cl_GV_inner;
22 template <class T> class cl_GV_index;
23 template <class T> class cl_GV_constindex;
24 template <class T> struct cl_GV_vectorops;
29 std::size_t len; // number of elements
31 std::size_t size() const; // number of elements
32 cl_GV_vectorops<T>* vectorops; // get/set element
33 const cl_GV_index<T> operator[] (unsigned long index);
34 const cl_GV_constindex<T> operator[] (unsigned long index) const;
35 const cl_GV_index<T> operator[] (long index);
36 const cl_GV_constindex<T> operator[] (long index) const;
37 const cl_GV_index<T> operator[] (unsigned int index);
38 const cl_GV_constindex<T> operator[] (unsigned int index) const;
39 const cl_GV_index<T> operator[] (int index);
40 const cl_GV_constindex<T> operator[] (int index) const;
41 #if long_bitsize < pointer_bitsize
42 const cl_GV_index<T> operator[] (unsigned long long index);
43 const cl_GV_constindex<T> operator[] (unsigned long long index) const;
44 const cl_GV_index<T> operator[] (long long index);
45 const cl_GV_constindex<T> operator[] (long long index) const;
49 cl_GV_inner (std::size_t l, cl_GV_vectorops<T>* ops) : len (l), vectorops (ops) {}
53 // Ability to place an object at a given address.
54 void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
56 // No default constructor, copy constructor, assignment operator, new.
58 cl_GV_inner (const cl_GV_inner&);
59 cl_GV_inner& operator= (const cl_GV_inner&);
60 void* operator new (size_t size)
61 { (void)size; return (void*)1; } // SGI CC needs this definition
62 // Friend declarations. They are for the compiler. Just ignore them.
63 friend class cl_GV_index<T>;
64 friend class cl_GV_constindex<T>;
69 // This is the class of objects created by accessing a non-const vector
76 cl_GV_index (cl_GV_inner<T>* v, std::size_t i) : vec (v), index (i) {}
77 // Assignment operator.
78 void operator= (const T& x) const;
79 #if (defined(__sparc__) || defined(__sparc64__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug?
80 void operator= (const cl_GV_index<T>&) const;
81 void operator= (const cl_GV_constindex<T>&) const;
84 // No assignment operator.
85 cl_GV_index& operator= (const cl_GV_index&);
88 // No default constructor.
93 class cl_GV_constindex {
94 // This is the class of objects created by accessing a const vector
95 // through []. It lacks the assignment operator.
97 const cl_GV_inner<T>* vec;
101 cl_GV_constindex (const cl_GV_inner<T>* v, std::size_t i) : vec (v), index (i) {}
103 // No default constructor, assignment operator.
105 cl_GV_constindex& operator= (const cl_GV_constindex&);
109 struct cl_GV_vectorops {
110 const T (*element) (const cl_GV_inner<T>* vec, std::size_t index);
111 void (*set_element) (cl_GV_inner<T>* vec, std::size_t index, const T& x);
112 void (*do_delete) (cl_GV_inner<T>* vec);
113 void (*copy_elements) (const cl_GV_inner<T>* srcvec, std::size_t srcindex, cl_GV_inner<T>* destvec, std::size_t destindex, std::size_t count);
116 // All member functions are inline.
119 inline std::size_t cl_GV_inner<T>::size() const
125 inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (unsigned long index)
127 return cl_GV_index<T>(this,index);
131 inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (unsigned long index) const
133 return cl_GV_constindex<T>(this,index);
137 inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (long index)
139 return operator[]((unsigned long)index);
143 inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (long index) const
145 return operator[]((unsigned long)index);
149 inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (unsigned int index)
151 return operator[]((unsigned long)index);
155 inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (unsigned int index) const
157 return operator[]((unsigned long)index);
161 inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (int index)
163 return operator[]((unsigned long)index);
167 inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (int index) const
169 return operator[]((unsigned long)index);
172 #if long_bitsize < pointer_bitsize
175 inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (unsigned long long index)
177 return cl_GV_index<T>(this,index);
181 inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (unsigned long long index) const
183 return cl_GV_constindex<T>(this,index);
187 inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (long long index)
189 return operator[]((unsigned long)index);
193 inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (long long index) const
195 return operator[]((unsigned long)index);
201 inline cl_GV_inner<T>::~cl_GV_inner ()
203 vectorops->do_delete(this);
207 inline cl_GV_index<T>::operator T () const
209 #ifndef CL_GV_NO_RANGECHECKS
210 if (!(index < vec->len)) throw runtime_exception();
212 return vec->vectorops->element(vec,index);
216 inline void cl_GV_index<T>::operator= (const T& x) const
218 #ifndef CL_GV_NO_RANGECHECKS
219 if (!(index < vec->len)) throw runtime_exception();
221 vec->vectorops->set_element(vec,index,x);
225 inline cl_GV_constindex<T>::operator T () const
227 #ifndef CL_GV_NO_RANGECHECKS
228 if (!(index < vec->len)) throw runtime_exception();
230 return vec->vectorops->element(vec,index);
233 #if (defined(__sparc__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug? handle "y[j] = x[i];"
235 inline void cl_GV_index<T>::operator= (const cl_GV_index<T>& x) const
236 { operator= ((T) x); }
238 inline void cl_GV_index<T>::operator= (const cl_GV_constindex<T>& x) const
239 { operator= ((T) x); }
243 // In memory, a vector looks like this:
246 struct cl_heap_GV : cl_heap {
248 // here room for the elements
251 // And a reference to a vector always looks like this:
253 template <class T, class BASE>
254 struct cl_GV : public BASE {
257 std::size_t size() const
259 return ((const cl_heap_GV<T> *) this->pointer)->v.size();
261 // Reference. Forbid modification of `const cl_GV&' arguments.
262 const cl_GV_constindex<T> operator[] (unsigned long index) const
264 return ((const cl_heap_GV<T> *) this->pointer)->v[index];
266 const cl_GV_index<T> operator[] (unsigned long index)
268 return ((cl_heap_GV<T> *) this->pointer)->v[index];
270 const cl_GV_constindex<T> operator[] (long index) const
271 { return operator[]((unsigned long)index); }
272 const cl_GV_index<T> operator[] (long index)
273 { return operator[]((unsigned long)index); }
274 const cl_GV_constindex<T> operator[] (unsigned int index) const
275 { return operator[]((unsigned long)index); }
276 const cl_GV_index<T> operator[] (unsigned int index)
277 { return operator[]((unsigned long)index); }
278 const cl_GV_constindex<T> operator[] (int index) const
279 { return operator[]((unsigned long)index); }
280 const cl_GV_index<T> operator[] (int index)
281 { return operator[]((unsigned long)index); }
282 #if long_bitsize < pointer_bitsize
283 const cl_GV_constindex<T> operator[] (unsigned long long index) const
285 return ((const cl_heap_GV<T> *) this->pointer)->v[index];
287 const cl_GV_index<T> operator[] (unsigned long long index)
289 return ((cl_heap_GV<T> *) this->pointer)->v[index];
291 const cl_GV_constindex<T> operator[] (long long index) const
292 { return operator[]((unsigned long long)index); }
293 const cl_GV_index<T> operator[] (long long index)
294 { return operator[]((unsigned long long)index); }
297 cl_GV (const cl_GV&);
298 // Assignment operator.
299 cl_GV& operator= (const cl_GV&);
300 // Copy a piece of a vector into another vector.
301 // (Both vectors must be of the same type. Overlapping not allowed.)
302 static void copy_elements (const cl_GV& src, std::size_t srcindex, cl_GV& dest, std::size_t destindex, std::size_t count)
304 const cl_heap_GV<T> * hsrc = (const cl_heap_GV<T> *) src.pointer;
305 cl_heap_GV<T> * hdest = (cl_heap_GV<T> *) dest.pointer;
306 if (!(hsrc->v.vectorops == hdest->v.vectorops))
307 throw runtime_exception();
308 hsrc->v.vectorops->copy_elements(&hsrc->v,srcindex,&hdest->v,destindex,count);
310 // Private pointer manipulations.
311 operator cl_heap_GV<T>* () const;
312 cl_GV (cl_heap_GV<T>* p) : BASE ((cl_private_thing) p) {}
313 cl_GV (cl_private_thing p) : BASE (p) {}
315 // Forbid use of default constructor.
318 #define CL_GV(T,BASE) cl_GV<T,BASE>
319 // Define copy constructor.
320 template <class T, class BASE>
321 _CL_DEFINE_COPY_CONSTRUCTOR2(CL_GV(T,BASE),cl_GV,BASE)
322 // Define assignment operator.
323 template <class T, class BASE>
324 CL_DEFINE_ASSIGNMENT_OPERATOR(CL_GV(T,BASE),CL_GV(T,BASE))
325 // Private pointer manipulations. Never throw away a `struct cl_heap_GV<T> *'!
326 template <class T, class BASE>
327 inline CL_GV(T,BASE)::operator cl_heap_GV<T>* () const
329 cl_heap_GV<T>* hpointer = (cl_heap_GV<T>*)this->pointer;
330 cl_inc_refcount(*this);
335 // The "generic" general vector type.
337 typedef cl_heap_GV<cl_gcobject> cl_heap_GV_any;
338 typedef cl_GV<cl_gcobject,cl_V_any> cl_GV_any;
343 // Conversions to subtypes without checking:
344 #define The(type) *(const type *) & cl_identity
345 // This inline function is for type checking purposes only.
346 inline const cl_GV_any& cl_identity (const cl_GV_any& x) { return x; }
350 #endif /* _CL_GV_H */