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.
623 lines
18 KiB
623 lines
18 KiB
/*****************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 2000
|
|
*
|
|
* TITLE: gensph.h
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* AUTHOR: LazarI
|
|
*
|
|
* DATE: 23-Dec-2000
|
|
*
|
|
* DESCRIPTION: generic smart pointers & smart handles templates
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifndef _GENSPH_H_
|
|
#define _GENSPH_H_
|
|
|
|
// include the core definitions first
|
|
#include "coredefs.h"
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CGenericSP
|
|
//
|
|
// a generic smart pointer
|
|
// everything starts here -:)
|
|
//
|
|
template < class T,
|
|
class inheritorClass,
|
|
class pType = T*,
|
|
INT_PTR null = 0,
|
|
class pCType = const T* >
|
|
|
|
class CGenericSP
|
|
{
|
|
public:
|
|
// construction/destruction
|
|
CGenericSP(): m_p(GetNull()) {}
|
|
CGenericSP(pType p): m_p(GetNull()) { _Attach(p); }
|
|
~CGenericSP() { Reset(); }
|
|
|
|
// follows common smart pointer impl. -
|
|
// operators & methods
|
|
|
|
void Reset()
|
|
{
|
|
if( GetNull() != m_p )
|
|
{
|
|
_Delete(m_p);
|
|
m_p = GetNull();
|
|
}
|
|
}
|
|
|
|
void Attach(pType p)
|
|
{
|
|
Reset();
|
|
m_p = (p ? p : GetNull());
|
|
}
|
|
|
|
pType Detach()
|
|
{
|
|
pType p = GetNull();
|
|
if( GetNull() != m_p )
|
|
{
|
|
p = m_p;
|
|
m_p = GetNull();
|
|
}
|
|
return p;
|
|
}
|
|
|
|
template <class AS_TYPE>
|
|
AS_TYPE GetPtrAs() const
|
|
{
|
|
return (GetNull() == m_p) ? reinterpret_cast<AS_TYPE>(NULL) : reinterpret_cast<AS_TYPE>(m_p);
|
|
}
|
|
|
|
pType GetPtr() const
|
|
{
|
|
return GetPtrAs<pType>();
|
|
}
|
|
|
|
pType* GetPPT()
|
|
{
|
|
return static_cast<pType*>(&m_p);
|
|
}
|
|
|
|
pCType* GetPPCT()
|
|
{
|
|
return const_cast<pCType*>(&m_p);
|
|
}
|
|
|
|
void** GetPPV()
|
|
{
|
|
return reinterpret_cast<void**>(&m_p);
|
|
}
|
|
|
|
operator pType() const
|
|
{
|
|
return GetPtr();
|
|
}
|
|
|
|
T& operator*() const
|
|
{
|
|
ASSERT(GetNull() != m_p);
|
|
return *m_p;
|
|
}
|
|
|
|
pType* operator&()
|
|
{
|
|
ASSERT(GetNull() == m_p);
|
|
return GetPPT();
|
|
}
|
|
|
|
pType operator->() const
|
|
{
|
|
ASSERT(GetNull() != m_p);
|
|
return (pType)m_p;
|
|
}
|
|
|
|
pType operator=(pType p)
|
|
{
|
|
_Attach(p);
|
|
return m_p;
|
|
}
|
|
|
|
pType operator=(const int i)
|
|
{
|
|
// this operator is only for NULL assignment
|
|
ASSERT(INT2PTR(i, pType) == NULL || INT2PTR(i, pType) == GetNull());
|
|
Attach(INT2PTR(i, pType));
|
|
return m_p;
|
|
}
|
|
|
|
bool operator!() const
|
|
{
|
|
return (GetNull() == m_p);
|
|
}
|
|
|
|
bool operator<(pType p) const
|
|
{
|
|
return (m_p < p);
|
|
}
|
|
|
|
bool operator==(pType p) const
|
|
{
|
|
return (m_p == p);
|
|
}
|
|
|
|
protected:
|
|
pType m_p;
|
|
|
|
// those will be declared protected, so people won't use them directly
|
|
CGenericSP(CGenericSP<T, inheritorClass, pType, null, pCType> &sp): m_p(GetNull())
|
|
{
|
|
_Attach(sp);
|
|
}
|
|
|
|
void Attach(CGenericSP<T, inheritorClass, pType, null, pCType> &sp)
|
|
{
|
|
static_cast<inheritorClass*>(this)->Attach(static_cast<pType>(sp));
|
|
sp.Detach();
|
|
}
|
|
|
|
pType operator=(CGenericSP<T, inheritorClass, pType, null, pCType> &sp)
|
|
{
|
|
_Attach(sp);
|
|
return m_p;
|
|
}
|
|
|
|
// NULL support, use these to check for/assign NULL in inheritors
|
|
pType GetNull() const { return reinterpret_cast<pType>(null); }
|
|
bool IsNull(pType p) const { return GetNull() == p; }
|
|
bool IsntNull(pType p) const { return GetNull() != p; }
|
|
|
|
private:
|
|
void _Attach(pType p)
|
|
{
|
|
// give a chance to inheritors to override the attach
|
|
static_cast<inheritorClass*>(this)->Attach(p);
|
|
}
|
|
|
|
void _Attach(CGenericSP<T, inheritorClass, pType, null, pCType> &sp)
|
|
{
|
|
// give a chance to inheritors to override the attach
|
|
static_cast<inheritorClass*>(this)->Attach(sp);
|
|
}
|
|
|
|
void _Delete(pType p)
|
|
{
|
|
// the inheritor class defines static member called Delete(pType p)
|
|
// to destroy the object.
|
|
if( GetNull() != p )
|
|
{
|
|
#pragma prefast(suppress:307, "This is a known prefast bug fixed in version 1.2 (PREfast bug 616)")
|
|
inheritorClass::Delete(p);
|
|
}
|
|
}
|
|
};
|
|
|
|
// declares standard default contructor, copy constructor, attach
|
|
// contructor and assignment operators (they can't be inherited as constructors can't)
|
|
// for the CGenericSP class in an inheritor class.
|
|
#define DECLARE_GENERICSMARTPTR_CONSTRUCT(T, className) \
|
|
private: \
|
|
className(className &sp): CGenericSP< T, className >(sp) { } \
|
|
T* operator=(className &sp) \
|
|
{ return CGenericSP< T, className >::operator =(sp); } \
|
|
public: \
|
|
className() { } \
|
|
className(T *p): CGenericSP< T, className >(p) { } \
|
|
T* operator=(T *p) \
|
|
{ return CGenericSP< T, className >::operator =(p); } \
|
|
T* operator=(const int i) \
|
|
{ return CGenericSP< T, className >::operator =(i); } \
|
|
|
|
#define DECLARE_GENERICSMARTPTR_CONSTRUCT1(T, className, pType) \
|
|
private: \
|
|
className(className &sp): CGenericSP<T, className, pType>(sp) { } \
|
|
pType operator=(className &sp) \
|
|
{ return CGenericSP<T, className, pType>::operator =(sp); } \
|
|
public: \
|
|
className() { } \
|
|
className(pType p): CGenericSP<T, className, pType>(p) { } \
|
|
pType operator=(pType p) \
|
|
{ return CGenericSP<T, className, pType>::operator =(p); } \
|
|
pType operator=(const int i) \
|
|
{ return CGenericSP<T, className, pType>::operator =(i); } \
|
|
|
|
#define DECLARE_GENERICSMARTPTR_CONSTRUCT2(T, className, pType, null) \
|
|
private: \
|
|
className(className &sp): CGenericSP<T, className, pType, null>(sp) { } \
|
|
pType operator=(className &sp) \
|
|
{ return CGenericSP<T, className, pType, null>::operator =(sp); } \
|
|
public: \
|
|
className() { } \
|
|
className(pType p): CGenericSP<T, className, pType, null>(p) { } \
|
|
pType operator=(pType p) \
|
|
{ return CGenericSP<T, className, pType, null>::operator =(p); } \
|
|
pType operator=(const int i) \
|
|
{ return CGenericSP<T, className, pType, null>::operator =(i); } \
|
|
|
|
////////////////////////////////////////////////
|
|
////////// AUTO POINTERS ///////////////////////
|
|
////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoPtr
|
|
//
|
|
// simple auto-pointer
|
|
// uses delete operator to free memory
|
|
//
|
|
template <class T>
|
|
class CAutoPtr: public CGenericSP< T, CAutoPtr<T> >
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT(T, CAutoPtr<T>)
|
|
static void Delete(T *p) { delete p; }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoPtrArray
|
|
//
|
|
// simple auto-pointer allocated as array
|
|
// uses delete[] operator to free memory
|
|
//
|
|
template <class T>
|
|
class CAutoPtrArray: public CGenericSP< T, CAutoPtrArray<T> >
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT(T, CAutoPtrArray<T>)
|
|
static void Delete(T *p) { delete[] p; }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoPtrCRT
|
|
//
|
|
// simple CRT auto-pointer - allocated with malloc/calloc
|
|
// uses free to free the memory
|
|
//
|
|
template <class T>
|
|
class CAutoPtrCRT: public CGenericSP< T, CAutoPtrCRT<T> >
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT(T, CAutoPtrCRT<T>)
|
|
static void Delete(T *p) { free(p); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoPtrSpl
|
|
//
|
|
// simple spooler auto-pointer -
|
|
// uses FreeMem to free memory
|
|
//
|
|
template <class T>
|
|
class CAutoPtrSpl: public CGenericSP< T, CAutoPtrSpl<T> >
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT(T, CAutoPtrSpl<T>)
|
|
static void Delete(T *p) { FreeMem(p); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoPtrBSTR
|
|
//
|
|
// simple BSTR auto-pointer -
|
|
// SysAllocString/SysFreeString
|
|
//
|
|
class CAutoPtrBSTR: public CGenericSP<BSTR, CAutoPtrBSTR, BSTR>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(BSTR, CAutoPtrBSTR, BSTR)
|
|
static void Delete(BSTR p) { SysFreeString(p); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoPtrCOM
|
|
//
|
|
// simple smart COM pointer
|
|
//
|
|
template <class T>
|
|
class CAutoPtrCOM: public CGenericSP< T, CAutoPtrCOM<T> >
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT(T, CAutoPtrCOM<T>)
|
|
static void Delete(T *p) { p->Release(); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CRefPtrCOM
|
|
//
|
|
// referenced smart COM pointer (ATL style)
|
|
// with improvements for robustness
|
|
//
|
|
template <class T>
|
|
class CRefPtrCOM: public CGenericSP< T, CRefPtrCOM<T> >
|
|
{
|
|
void _AddRefAttach(T *p);
|
|
public:
|
|
// special case all these
|
|
CRefPtrCOM() { }
|
|
CRefPtrCOM(const CGenericSP< T, CRefPtrCOM<T> > &sp): CGenericSP< T, CRefPtrCOM<T> >(sp) { }
|
|
T* operator=(const CRefPtrCOM<T> &sp) { return CGenericSP< T, CRefPtrCOM<T> >::operator =(sp); }
|
|
T* operator=(const int i) { return CGenericSP< T, CRefPtrCOM<T> >::operator =(i); }
|
|
|
|
// overloaded stuff
|
|
void Attach(const CRefPtrCOM<T> &sp) { _AddRefAttach(static_cast<T*>(sp)); }
|
|
static void Delete(T *p) { p->Release(); }
|
|
|
|
// use these functions instead of operators (more clear)
|
|
HRESULT CopyFrom(T *p); // AddRef p and assign to this
|
|
HRESULT CopyTo(T **ppObj); // AddRef this and assign to ppObj
|
|
HRESULT TransferTo(T **ppObj); // assign this to ppObj and assign NULL to this
|
|
HRESULT Adopt(T *p); // take ownership of p
|
|
|
|
private:
|
|
// disable contruction, assignment operator & attach from
|
|
// a raw pointer - it's not clear what exactly you want:
|
|
// to copy (AddRef) the object or to take ownership - use
|
|
// the functions above to make clear
|
|
void Attach(T* p);
|
|
CRefPtrCOM(T *p);
|
|
T* operator=(T *p);
|
|
};
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoPtrShell
|
|
//
|
|
// smart shell auto pointer -
|
|
// uses shell IMalloc to free memory
|
|
//
|
|
template <class T>
|
|
class CAutoPtrShell: public CGenericSP< T, CAutoPtrShell<T> >
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT(T, CAutoPtrShell<T>)
|
|
static void Delete(T *p)
|
|
{
|
|
CAutoPtrCOM<IMalloc> spShellMalloc;
|
|
if( SUCCEEDED(SHGetMalloc(&spShellMalloc)) )
|
|
{
|
|
spShellMalloc->Free(p);
|
|
}
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoPtrPIDL
|
|
//
|
|
// smart shell ID list ptr - LPCITEMIDLIST, LPITEMIDLIST.
|
|
//
|
|
typedef CAutoPtrShell<ITEMIDLIST> CAutoPtrPIDL;
|
|
|
|
////////////////////////////////////////////////
|
|
////////// AUTO HANDLES ////////////////////////
|
|
////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleNT
|
|
//
|
|
// NT kernel object handle (closed with CloseHandle)
|
|
//
|
|
class CAutoHandleNT: public CGenericSP<HANDLE, CAutoHandleNT, HANDLE>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HANDLE, CAutoHandleNT, HANDLE)
|
|
static void Delete(HANDLE h) { VERIFY(CloseHandle(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleHLOCAL
|
|
//
|
|
// NT local heap handle (closed with LocalFree)
|
|
//
|
|
class CAutoHandleHLOCAL: public CGenericSP<HLOCAL, CAutoHandleHLOCAL, HLOCAL>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HLOCAL, CAutoHandleHLOCAL, HLOCAL)
|
|
static void Delete(HLOCAL h) { VERIFY(NULL == LocalFree(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleHGLOBAL
|
|
//
|
|
// NT global heap handle (closed with GlobalFree)
|
|
//
|
|
class CAutoHandleHGLOBAL: public CGenericSP<HGLOBAL, CAutoHandleHGLOBAL, HGLOBAL>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HGLOBAL, CAutoHandleHGLOBAL, HGLOBAL)
|
|
static void Delete(HGLOBAL h) { VERIFY(NULL == GlobalFree(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandlePrinter
|
|
//
|
|
// auto printer handle
|
|
//
|
|
class CAutoHandlePrinter: public CGenericSP<HANDLE, CAutoHandlePrinter, HANDLE>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HANDLE, CAutoHandlePrinter, HANDLE)
|
|
static void Delete(HANDLE h) { CHECK(ClosePrinter(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandlePrinterNotify
|
|
//
|
|
// printer notifications handle -
|
|
// Find[Firse/Next/Close]PrinterChangeNotification()
|
|
//
|
|
class CAutoHandlePrinterNotify: public CGenericSP<HANDLE, CAutoHandlePrinterNotify, HANDLE, -1>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT2(HANDLE, CAutoHandlePrinterNotify, HANDLE, -1)
|
|
static void Delete(HANDLE h) { CHECK(FindClosePrinterChangeNotification(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoPtrPrinterNotify
|
|
//
|
|
// printer notifications memory - spooler should free it.
|
|
// Find[Firse/Next/Close]PrinterChangeNotification()
|
|
//
|
|
class CAutoPtrPrinterNotify: public CGenericSP<PRINTER_NOTIFY_INFO, CAutoPtrPrinterNotify>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT(PRINTER_NOTIFY_INFO, CAutoPtrPrinterNotify)
|
|
static void Delete(PRINTER_NOTIFY_INFO *p) { CHECK(FreePrinterNotifyInfo(p)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleGDI
|
|
//
|
|
// GDI auto handle (WindowsNT GDI handle wrapper)
|
|
//
|
|
template <class T>
|
|
class CAutoHandleGDI: public CGenericSP< T, CAutoHandleGDI<T>, T >
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(T, CAutoHandleGDI<T>, T)
|
|
static void Delete(T hGDIObj) { VERIFY(DeleteObject(hGDIObj)); }
|
|
};
|
|
|
|
// GDI auto handles
|
|
typedef CAutoHandleGDI<HPEN> CAutoHandlePen;
|
|
typedef CAutoHandleGDI<HBRUSH> CAutoHandleBrush;
|
|
typedef CAutoHandleGDI<HFONT> CAutoHandleFont;
|
|
typedef CAutoHandleGDI<HBITMAP> CAutoHandleBitmap;
|
|
// etc...
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleCursor
|
|
//
|
|
// auto handle for HCURSOR
|
|
//
|
|
class CAutoHandleCursor: public CGenericSP<HCURSOR, CAutoHandleCursor, HCURSOR>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HCURSOR, CAutoHandleCursor, HCURSOR)
|
|
static void Delete(HCURSOR h) { VERIFY(DestroyCursor(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleIcon
|
|
//
|
|
// auto handle for HICON
|
|
//
|
|
class CAutoHandleIcon: public CGenericSP<HICON, CAutoHandleIcon, HICON>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HICON, CAutoHandleIcon, HICON)
|
|
static void Delete(HICON h) { VERIFY(DestroyIcon(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleMenu
|
|
//
|
|
// auto handle for HMENU
|
|
//
|
|
class CAutoHandleMenu: public CGenericSP<HMENU, CAutoHandleMenu, HMENU>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HMENU, CAutoHandleMenu, HMENU)
|
|
static void Delete(HMENU h) { VERIFY(DestroyMenu(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleAccel
|
|
//
|
|
// auto handle for HACCEL
|
|
//
|
|
class CAutoHandleAccel: public CGenericSP<HACCEL, CAutoHandleAccel, HACCEL>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HACCEL, CAutoHandleAccel, HACCEL)
|
|
static void Delete(HACCEL h) { DestroyAcceleratorTable(h); }
|
|
};
|
|
|
|
#ifdef _INC_COMCTRLP
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleHDSA
|
|
//
|
|
// auto handle for shell HDSA
|
|
// (dynamic structure arrays)
|
|
//
|
|
class CAutoHandleHDSA: public CGenericSP<HDSA, CAutoHandleHDSA, HDSA>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HDSA, CAutoHandleHDSA, HDSA)
|
|
static void Delete(HDSA h) { VERIFY(DSA_Destroy(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleMRU
|
|
//
|
|
// auto handle for MRU (shell common controls)
|
|
// CreateMRUList/FreeMRUList
|
|
//
|
|
class CAutoHandleMRU: public CGenericSP<HANDLE, CAutoHandleMRU, HANDLE>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HANDLE, CAutoHandleMRU, HANDLE)
|
|
static void Delete(HANDLE h) { FreeMRUList(h); }
|
|
};
|
|
#endif // _INC_COMCTRLP
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleHKEY
|
|
//
|
|
// auto handle for a Windows registry key (HKEY)
|
|
// RegCreateKeyEx/RegOpenKeyEx/RegCloseKey
|
|
//
|
|
class CAutoHandleHKEY: public CGenericSP<HKEY, CAutoHandleHKEY, HKEY>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HKEY, CAutoHandleHKEY, HKEY)
|
|
static void Delete(HKEY h) { VERIFY(ERROR_SUCCESS == RegCloseKey(h)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////
|
|
//
|
|
// class CAutoHandleHMODULE
|
|
//
|
|
// auto handle for a HMODULE
|
|
// LoadLibrary/FreeLibrary
|
|
//
|
|
class CAutoHandleHMODULE: public CGenericSP<HMODULE, CAutoHandleHMODULE, HMODULE>
|
|
{
|
|
public:
|
|
DECLARE_GENERICSMARTPTR_CONSTRUCT1(HMODULE, CAutoHandleHMODULE, HMODULE)
|
|
static void Delete(HMODULE h) { VERIFY(FreeLibrary(h)); }
|
|
};
|
|
|
|
// include the implementation of the template classes here
|
|
#include "gensph.inl"
|
|
|
|
#endif // endif _GENSPH_H_
|