You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							301 lines
						
					
					
						
							8.9 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							301 lines
						
					
					
						
							8.9 KiB
						
					
					
				| // General vectors. | |
|  | |
| #ifndef _CL_GV_H | |
| #define _CL_GV_H | |
|  | |
| #include "cln/object.h" | |
| #include "cln/V.h" | |
| #include "cln/exception.h" | |
| #include <cstdlib> | |
|  | |
| namespace cln { | |
| 
 | |
| // A vector is a structure having the following interface: | |
| //     v.length()        returns the number of elements | |
| //     v[i]              returns the i-th element (0<=i<length), as a | |
| //                       pseudo-lvalue (you can assign to it, but not take its | |
| //                       address - exactly what you want for bit-vectors) | |
| // This is implemented by letting v[i] be of a special "vector index" type. | |
|  | |
| template <class T> class cl_GV_inner; | |
| template <class T> class cl_GV_index; | |
| template <class T> class cl_GV_constindex; | |
| template <class T> struct cl_GV_vectorops; | |
| 
 | |
| template <class T> | |
| class cl_GV_inner { | |
| protected: | |
| 	uintC len; // number of elements | |
| public: | |
| 	uintC length () const; // number of elements | |
| 	cl_GV_vectorops<T>* vectorops; // get/set element | |
| 	const cl_GV_index<T> operator[] (unsigned long index); | |
| 	const cl_GV_constindex<T> operator[] (unsigned long index) const; | |
| 	const cl_GV_index<T> operator[] (long index); | |
| 	const cl_GV_constindex<T> operator[] (long index) const; | |
| 	const cl_GV_index<T> operator[] (unsigned int index); | |
| 	const cl_GV_constindex<T> operator[] (unsigned int index) const; | |
| 	const cl_GV_index<T> operator[] (int index); | |
| 	const cl_GV_constindex<T> operator[] (int index) const; | |
| public: /* ugh */ | |
| 	// Constructor. | |
| 	cl_GV_inner (uintC l, cl_GV_vectorops<T>* ops) : len (l), vectorops (ops) {} | |
| public: | |
| 	// Destructor. | |
| 	~cl_GV_inner (); | |
| 	// Ability to place an object at a given address. | |
| 	void* operator new (size_t size, void* ptr) { (void)size; return ptr; } | |
| private: | |
| // No default constructor, copy constructor, assignment operator, new. | |
| 	cl_GV_inner (); | |
| 	cl_GV_inner (const cl_GV_inner&); | |
| 	cl_GV_inner& operator= (const cl_GV_inner&); | |
| 	void* operator new (size_t size) | |
| 		{ (void)size; return (void*)1; } // SGI CC needs this definition | |
| // Friend declarations. They are for the compiler. Just ignore them. | |
| 	friend class cl_GV_index<T>; | |
| 	friend class cl_GV_constindex<T>; | |
| }; | |
| 
 | |
| template <class T> | |
| class cl_GV_index { | |
| 	// This is the class of objects created by accessing a non-const vector | |
| 	// through []. | |
| public: | |
| 	cl_GV_inner<T>* vec; | |
| 	uintC index; | |
| 	operator T () const; | |
| 	// Constructor: | |
| 	cl_GV_index (cl_GV_inner<T>* v, uintC i) : vec (v), index (i) {} | |
| 	// Assignment operator. | |
| 	void operator= (const T& x) const; | |
| #if (defined(__sparc__) || defined(__sparc64__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug? | |
| 	void operator= (const cl_GV_index<T>&) const; | |
| 	void operator= (const cl_GV_constindex<T>&) const; | |
| #else | |
| private: | |
| 	// No assignment operator. | |
| 	cl_GV_index& operator= (const cl_GV_index&); | |
| #endif | |
| private: | |
| // No default constructor. | |
| 	cl_GV_index (); | |
| }; | |
| 
 | |
| template <class T> | |
| class cl_GV_constindex { | |
| 	// This is the class of objects created by accessing a const vector | |
| 	// through []. It lacks the assignment operator. | |
| public: | |
| 	const cl_GV_inner<T>* vec; | |
| 	uintC index; | |
| 	operator T () const; | |
| 	// Constructor: | |
| 	cl_GV_constindex (const cl_GV_inner<T>* v, uintC i) : vec (v), index (i) {} | |
| private: | |
| // No default constructor, assignment operator. | |
| 	cl_GV_constindex (); | |
| 	cl_GV_constindex& operator= (const cl_GV_constindex&); | |
| }; | |
| 
 | |
| template <class T> | |
| struct cl_GV_vectorops { | |
| 	const T (*element) (const cl_GV_inner<T>* vec, uintC index); | |
| 	void (*set_element) (cl_GV_inner<T>* vec, uintC index, const T& x); | |
| 	void (*do_delete) (cl_GV_inner<T>* vec); | |
| 	void (*copy_elements) (const cl_GV_inner<T>* srcvec, uintC srcindex, cl_GV_inner<T>* destvec, uintC destindex, uintC count); | |
| }; | |
| 
 | |
| // All member functions are inline. | |
|  | |
| template <class T> | |
| inline uintC cl_GV_inner<T>::length () const | |
| { | |
| 	return len; | |
| } | |
| 
 | |
| template <class T> | |
| inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (unsigned long index) | |
| { | |
| 	return cl_GV_index<T>(this,index); | |
| } | |
| 
 | |
| template <class T> | |
| inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (unsigned long index) const | |
| { | |
| 	return cl_GV_constindex<T>(this,index); | |
| } | |
| 
 | |
| template <class T> | |
| inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (long index) | |
| { | |
| 	return operator[]((unsigned long)index); | |
| } | |
| 
 | |
| template <class T> | |
| inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (long index) const | |
| { | |
| 	return operator[]((unsigned long)index); | |
| } | |
| 
 | |
| template <class T> | |
| inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (unsigned int index) | |
| { | |
| 	return operator[]((unsigned long)index); | |
| } | |
| 
 | |
| template <class T> | |
| inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (unsigned int index) const | |
| { | |
| 	return operator[]((unsigned long)index); | |
| } | |
| 
 | |
| template <class T> | |
| inline const cl_GV_index<T> cl_GV_inner<T>::operator[] (int index) | |
| { | |
| 	return operator[]((unsigned long)index); | |
| } | |
| 
 | |
| template <class T> | |
| inline const cl_GV_constindex<T> cl_GV_inner<T>::operator[] (int index) const | |
| { | |
| 	return operator[]((unsigned long)index); | |
| } | |
| 
 | |
| template <class T> | |
| inline cl_GV_inner<T>::~cl_GV_inner () | |
| { | |
| 	vectorops->do_delete(this); | |
| } | |
| 
 | |
| template <class T> | |
| inline cl_GV_index<T>::operator T () const | |
| { | |
| 	#ifndef CL_GV_NO_RANGECHECKS | |
| 	if (!(index < vec->len)) throw runtime_exception(); | |
| 	#endif | |
| 	return vec->vectorops->element(vec,index); | |
| } | |
| 
 | |
| template <class T> | |
| inline void cl_GV_index<T>::operator= (const T& x) const | |
| { | |
| 	#ifndef CL_GV_NO_RANGECHECKS | |
| 	if (!(index < vec->len)) throw runtime_exception(); | |
| 	#endif | |
| 	vec->vectorops->set_element(vec,index,x); | |
| } | |
| 
 | |
| template <class T> | |
| inline cl_GV_constindex<T>::operator T () const | |
| { | |
| 	#ifndef CL_GV_NO_RANGECHECKS | |
| 	if (!(index < vec->len)) throw runtime_exception(); | |
| 	#endif | |
| 	return vec->vectorops->element(vec,index); | |
| } | |
| 
 | |
| #if (defined(__sparc__) || defined(__mips__) || defined(__mips64__)) && !defined(__GNUC__) // maybe an SGI CC and Sun CC bug? handle "y[j] = x[i];" | |
| template <class T> | |
| inline void cl_GV_index<T>::operator= (const cl_GV_index<T>& x) const | |
| { operator= ((T) x); } | |
| template <class T> | |
| inline void cl_GV_index<T>::operator= (const cl_GV_constindex<T>& x) const | |
| { operator= ((T) x); } | |
| #endif | |
|  | |
| 
 | |
| // In memory, a vector looks like this: | |
|  | |
| template <class T> | |
| struct cl_heap_GV : cl_heap { | |
| 	cl_GV_inner<T> v; | |
| 	// here room for the elements | |
| }; | |
| 
 | |
| // And a reference to a vector always looks like this: | |
|  | |
| template <class T, class BASE> | |
| struct cl_GV : public BASE { | |
| public: | |
| 	// Length. | |
| 	uintC length () const | |
| 	{ | |
| 		return ((const cl_heap_GV<T> *) this->pointer)->v.length(); | |
| 	} | |
| 	// Reference. Forbid modification of `const cl_GV&' arguments. | |
| 	const cl_GV_constindex<T> operator[] (unsigned long index) const | |
| 	{ | |
| 		return ((const cl_heap_GV<T> *) this->pointer)->v[index]; | |
| 	} | |
| 	const cl_GV_index<T> operator[] (unsigned long index) | |
| 	{ | |
| 		return ((cl_heap_GV<T> *) this->pointer)->v[index]; | |
| 	} | |
| 	const cl_GV_constindex<T> operator[] (long index) const | |
| 	{ return operator[]((unsigned long)index); } | |
| 	const cl_GV_index<T> operator[] (long index) | |
| 	{ return operator[]((unsigned long)index); } | |
| 	const cl_GV_constindex<T> operator[] (unsigned int index) const | |
| 	{ return operator[]((unsigned long)index); } | |
| 	const cl_GV_index<T> operator[] (unsigned int index) | |
| 	{ return operator[]((unsigned long)index); } | |
| 	const cl_GV_constindex<T> operator[] (int index) const | |
| 	{ return operator[]((unsigned long)index); } | |
| 	const cl_GV_index<T> operator[] (int index) | |
| 	{ return operator[]((unsigned long)index); } | |
| 	// Copy constructor. | |
| 	cl_GV (const cl_GV&); | |
| 	// Assignment operator. | |
| 	cl_GV& operator= (const cl_GV&); | |
| 	// Copy a piece of a vector into another vector. | |
| 	// (Both vectors must be of the same type. Overlapping not allowed.) | |
| 	static void copy_elements (const cl_GV& src, uintC srcindex, cl_GV& dest, uintC destindex, uintC count) | |
| 	{ | |
| 		const cl_heap_GV<T> * hsrc = (const cl_heap_GV<T> *) src.pointer; | |
| 		cl_heap_GV<T> * hdest = (cl_heap_GV<T> *) dest.pointer; | |
| 		if (!(hsrc->v.vectorops == hdest->v.vectorops)) | |
| 			throw runtime_exception(); | |
| 		hsrc->v.vectorops->copy_elements(&hsrc->v,srcindex,&hdest->v,destindex,count); | |
| 	} | |
| 	// Private pointer manipulations. | |
| 	operator cl_heap_GV<T>* () const; | |
| 	cl_GV (cl_heap_GV<T>* p) : BASE ((cl_private_thing) p) {} | |
| 	cl_GV (cl_private_thing p) : BASE (p) {} | |
| protected: | |
| 	// Forbid use of default constructor. | |
| 	cl_GV (); | |
| }; | |
| #define CL_GV(T,BASE) cl_GV<T,BASE> | |
| // Define copy constructor. | |
| template <class T, class BASE> | |
| 	_CL_DEFINE_COPY_CONSTRUCTOR2(CL_GV(T,BASE),cl_GV,BASE) | |
| // Define assignment operator. | |
| template <class T, class BASE> | |
| 	CL_DEFINE_ASSIGNMENT_OPERATOR(CL_GV(T,BASE),CL_GV(T,BASE)) | |
| // Private pointer manipulations. Never throw away a `struct cl_heap_GV<T> *'! | |
| template <class T, class BASE> | |
| inline CL_GV(T,BASE)::operator cl_heap_GV<T>* () const | |
| { | |
| 	cl_heap_GV<T>* hpointer = (cl_heap_GV<T>*)this->pointer; | |
| 	cl_inc_refcount(*this); | |
| 	return hpointer; | |
| } | |
| #undef CL_GV | |
|  | |
| // The "generic" general vector type. | |
|  | |
| typedef cl_heap_GV<cl_gcobject> cl_heap_GV_any; | |
| typedef cl_GV<cl_gcobject,cl_V_any> cl_GV_any; | |
| 
 | |
| 
 | |
| // Hack section. | |
|  | |
| // Conversions to subtypes without checking: | |
|   #define The(type)  *(const type *) & cl_identity | |
| // This inline function is for type checking purposes only. | |
|   inline const cl_GV_any& cl_identity (const cl_GV_any& x) { return x; } | |
| 
 | |
| }  // namespace cln | |
|  | |
| #endif /* _CL_GV_H */
 |