summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/appMain.cpp24
-rw-r--r--shared/appMain.h21
-rw-r--r--shared/customButton.cpp6
-rw-r--r--shared/dragAndDrop.cpp22
-rw-r--r--shared/dragAndDrop.h70
-rw-r--r--shared/fileError.h24
-rw-r--r--shared/fileHandling.cpp271
-rw-r--r--shared/fileHandling.h98
-rw-r--r--shared/fileTraverser.cpp20
-rw-r--r--shared/fileTraverser.h78
-rw-r--r--shared/globalFunctions.cpp78
-rw-r--r--shared/globalFunctions.h288
-rw-r--r--shared/localization.cpp27
-rw-r--r--shared/localization.h72
-rw-r--r--shared/loki/AbstractFactory.h185
-rw-r--r--shared/loki/Allocator.h153
-rw-r--r--shared/loki/AssocVector.h358
-rw-r--r--shared/loki/CachedFactory.h1167
-rw-r--r--shared/loki/CheckReturn.h165
-rw-r--r--shared/loki/Checker.h516
-rw-r--r--shared/loki/ConstPolicy.h61
-rw-r--r--shared/loki/DataGenerators.h113
-rw-r--r--shared/loki/EmptyType.h49
-rw-r--r--shared/loki/Factory.h1084
-rw-r--r--shared/loki/Function.h373
-rw-r--r--shared/loki/Functor.h1789
-rw-r--r--shared/loki/HierarchyGenerators.h291
-rw-r--r--shared/loki/Key.h764
-rw-r--r--shared/loki/LevelMutex.h1211
-rw-r--r--shared/loki/LockingPtr.h110
-rw-r--r--shared/loki/LokiExport.h69
-rw-r--r--shared/loki/LokiTypeInfo.h103
-rw-r--r--shared/loki/MultiMethods.h415
-rw-r--r--shared/loki/NullType.h34
-rw-r--r--shared/loki/OrderedStatic.h225
-rw-r--r--shared/loki/Pimpl.h198
-rw-r--r--shared/loki/RefToValue.h70
-rw-r--r--shared/loki/Register.h134
-rw-r--r--shared/loki/SPCachedFactory.h204
-rw-r--r--shared/loki/SafeBits.h514
-rw-r--r--shared/loki/SafeFormat.h590
-rw-r--r--shared/loki/ScopeGuard.h666
-rw-r--r--shared/loki/Sequence.h49
-rw-r--r--shared/loki/Singleton.h889
-rw-r--r--shared/loki/SmallObj.cpp1226
-rw-r--r--shared/loki/SmallObj.h644
-rw-r--r--shared/loki/SmartPtr.h1778
-rw-r--r--shared/loki/StrongPtr.h1697
-rw-r--r--shared/loki/Threads.h609
-rw-r--r--shared/loki/Tuple.h22
-rw-r--r--shared/loki/TypeManip.h284
-rw-r--r--shared/loki/TypeTraits.h2228
-rw-r--r--shared/loki/Typelist.h459
-rw-r--r--shared/loki/TypelistMacros.h353
-rw-r--r--shared/loki/Visitor.h355
-rw-r--r--shared/loki/readme.txt12
-rw-r--r--shared/loki/static_check.h45
-rw-r--r--shared/shadow.cpp8
-rw-r--r--shared/shadow.h24
-rw-r--r--shared/standardPaths.cpp11
-rw-r--r--shared/standardPaths.h10
-rw-r--r--shared/stringConv.h104
-rw-r--r--shared/systemConstants.h10
-rw-r--r--shared/systemFunctions.cpp18
-rw-r--r--shared/systemFunctions.h4
-rw-r--r--shared/tinyxml/tinyxml.cpp12
-rw-r--r--shared/tinyxml/tinyxmlparser.cpp20
-rw-r--r--shared/toggleButton.h4
-rw-r--r--shared/xmlBase.cpp3
-rw-r--r--shared/xmlBase.h182
-rw-r--r--shared/zstring.cpp24
-rw-r--r--shared/zstring.h31
72 files changed, 23185 insertions, 640 deletions
diff --git a/shared/appMain.cpp b/shared/appMain.cpp
new file mode 100644
index 00000000..fe6d3af5
--- /dev/null
+++ b/shared/appMain.cpp
@@ -0,0 +1,24 @@
+#include "appMain.h"
+#include <wx/window.h>
+#include <wx/app.h>
+
+using namespace FreeFileSync;
+
+
+bool AppMainWindow::mainWndAct = false;
+
+
+void FreeFileSync::AppMainWindow::setMainWindow(wxWindow* window)
+{
+ wxTheApp->SetTopWindow(window);
+ wxTheApp->SetExitOnFrameDelete(true);
+
+ assert (!mainWndAct);
+ mainWndAct = true;
+}
+
+
+bool AppMainWindow::mainWindowWasSet()
+{
+ return mainWndAct;
+}
diff --git a/shared/appMain.h b/shared/appMain.h
new file mode 100644
index 00000000..130a6e2a
--- /dev/null
+++ b/shared/appMain.h
@@ -0,0 +1,21 @@
+#ifndef APPMAIN_H_INCLUDED
+#define APPMAIN_H_INCLUDED
+
+class wxWindow;
+
+namespace FreeFileSync
+{
+//just some wrapper around a global variable representing the (logical) main application window
+class AppMainWindow
+{
+public:
+ static void setMainWindow(wxWindow* window); //set main window and enable "exit on frame delete"
+ static bool mainWindowWasSet();
+
+private:
+ static bool mainWndAct;
+};
+}
+
+
+#endif // APPMAIN_H_INCLUDED
diff --git a/shared/customButton.cpp b/shared/customButton.cpp
index 4027d3ef..40c0397f 100644
--- a/shared/customButton.cpp
+++ b/shared/customButton.cpp
@@ -10,9 +10,9 @@ wxButtonWithImage::wxButtonWithImage(wxWindow *parent,
long style,
const wxValidator& validator,
const wxString& name) :
- wxBitmapButton(parent, id, wxNullBitmap, pos, size, style | wxBU_AUTODRAW, validator, name),
- m_spaceAfter(0),
- m_spaceBefore(0)
+ wxBitmapButton(parent, id, wxNullBitmap, pos, size, style | wxBU_AUTODRAW, validator, name),
+ m_spaceAfter(0),
+ m_spaceBefore(0)
{
setTextLabel(label);
}
diff --git a/shared/dragAndDrop.cpp b/shared/dragAndDrop.cpp
index 9261d604..89f4da4d 100644
--- a/shared/dragAndDrop.cpp
+++ b/shared/dragAndDrop.cpp
@@ -19,9 +19,9 @@ class FFSFileDropEvent : public wxCommandEvent
{
public:
FFSFileDropEvent(const wxString& nameDropped, const wxWindow* dropWindow) :
- wxCommandEvent(FFS_DROP_FILE_EVENT),
- nameDropped_(nameDropped),
- dropWindow_(dropWindow) {}
+ wxCommandEvent(FFS_DROP_FILE_EVENT),
+ nameDropped_(nameDropped),
+ dropWindow_(dropWindow) {}
virtual wxEvent* Clone() const
{
@@ -39,7 +39,7 @@ class WindowDropTarget : public wxFileDropTarget
{
public:
WindowDropTarget(wxWindow* dropWindow) :
- dropWindow_(dropWindow) {}
+ dropWindow_(dropWindow) {}
virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
{
@@ -68,10 +68,10 @@ DragDropOnMainDlg::DragDropOnMainDlg(wxWindow* dropWindow1,
wxWindow* dropWindow2,
wxDirPickerCtrl* dirPicker,
wxComboBox* dirName) :
- dropWindow1_(dropWindow1),
- dropWindow2_(dropWindow2),
- dirPicker_(dirPicker),
- dirName_(dirName)
+ dropWindow1_(dropWindow1),
+ dropWindow2_(dropWindow2),
+ dirPicker_(dirPicker),
+ dirName_(dirName)
{
//prepare drag & drop
dropWindow1->SetDropTarget(new WindowDropTarget(dropWindow1)); //takes ownership
@@ -155,9 +155,9 @@ using FreeFileSync::DragDropOnDlg;
DragDropOnDlg::DragDropOnDlg(wxWindow* dropWindow,
wxDirPickerCtrl* dirPicker,
wxTextCtrl* dirName) :
- dropWindow_(dropWindow),
- dirPicker_(dirPicker),
- dirName_(dirName)
+ dropWindow_(dropWindow),
+ dirPicker_(dirPicker),
+ dirName_(dirName)
{
//prepare drag & drop
dropWindow->SetDropTarget(new WindowDropTarget(dropWindow)); //takes ownership
diff --git a/shared/dragAndDrop.h b/shared/dragAndDrop.h
index a8c7561a..4e6bbd31 100644
--- a/shared/dragAndDrop.h
+++ b/shared/dragAndDrop.h
@@ -15,48 +15,48 @@ class wxFileDirPickerEvent;
namespace FreeFileSync
{
- //add drag and drop functionality, coordinating a wxWindow, wxDirPickerCtrl, and wxComboBox/wxTextCtrl
+//add drag and drop functionality, coordinating a wxWindow, wxDirPickerCtrl, and wxComboBox/wxTextCtrl
- class DragDropOnMainDlg : private wxEvtHandler
- {
- public:
- DragDropOnMainDlg(wxWindow* dropWindow1,
- wxWindow* dropWindow2,
- wxDirPickerCtrl* dirPicker,
- wxComboBox* dirName);
-
- virtual ~DragDropOnMainDlg() {}
-
- virtual bool AcceptDrop(const wxString& dropName) = 0; //return true if drop should be processed
+class DragDropOnMainDlg : private wxEvtHandler
+{
+public:
+ DragDropOnMainDlg(wxWindow* dropWindow1,
+ wxWindow* dropWindow2,
+ wxDirPickerCtrl* dirPicker,
+ wxComboBox* dirName);
- private:
- void OnFilesDropped(FFSFileDropEvent& event);
- void OnWriteDirManually(wxCommandEvent& event);
- void OnDirSelected(wxFileDirPickerEvent& event);
+ virtual ~DragDropOnMainDlg() {}
- const wxWindow* dropWindow1_;
- const wxWindow* dropWindow2_;
- wxDirPickerCtrl* dirPicker_;
- wxComboBox* dirName_;
- };
+ virtual bool AcceptDrop(const wxString& dropName) = 0; //return true if drop should be processed
+private:
+ void OnFilesDropped(FFSFileDropEvent& event);
+ void OnWriteDirManually(wxCommandEvent& event);
+ void OnDirSelected(wxFileDirPickerEvent& event);
- class DragDropOnDlg: private wxEvtHandler
- {
- public:
- DragDropOnDlg(wxWindow* dropWindow,
- wxDirPickerCtrl* dirPicker,
- wxTextCtrl* dirName);
+ const wxWindow* dropWindow1_;
+ const wxWindow* dropWindow2_;
+ wxDirPickerCtrl* dirPicker_;
+ wxComboBox* dirName_;
+};
- private:
- void OnFilesDropped(FFSFileDropEvent& event);
- void OnWriteDirManually(wxCommandEvent& event);
- void OnDirSelected(wxFileDirPickerEvent& event);
- const wxWindow* dropWindow_;
- wxDirPickerCtrl* dirPicker_;
- wxTextCtrl* dirName_;
- };
+class DragDropOnDlg: private wxEvtHandler
+{
+public:
+ DragDropOnDlg(wxWindow* dropWindow,
+ wxDirPickerCtrl* dirPicker,
+ wxTextCtrl* dirName);
+
+private:
+ void OnFilesDropped(FFSFileDropEvent& event);
+ void OnWriteDirManually(wxCommandEvent& event);
+ void OnDirSelected(wxFileDirPickerEvent& event);
+
+ const wxWindow* dropWindow_;
+ wxDirPickerCtrl* dirPicker_;
+ wxTextCtrl* dirName_;
+};
}
diff --git a/shared/fileError.h b/shared/fileError.h
index f5c6bdbd..daf97910 100644
--- a/shared/fileError.h
+++ b/shared/fileError.h
@@ -6,20 +6,20 @@
namespace FreeFileSync
{
- class FileError //Exception class used to notify file/directory copy/delete errors
- {
- public:
- FileError(const wxString& message) :
- errorMessage(message) {}
+class FileError //Exception class used to notify file/directory copy/delete errors
+{
+public:
+ FileError(const wxString& message) :
+ errorMessage(message) {}
- const wxString& show() const
- {
- return errorMessage;
- }
+ const wxString& show() const
+ {
+ return errorMessage;
+ }
- private:
- wxString errorMessage;
- };
+private:
+ wxString errorMessage;
+};
}
#endif // FILEERROR_H_INCLUDED
diff --git a/shared/fileHandling.cpp b/shared/fileHandling.cpp
index 55fd7ff5..cea701cc 100644
--- a/shared/fileHandling.cpp
+++ b/shared/fileHandling.cpp
@@ -1,6 +1,7 @@
#include "fileHandling.h"
#include <wx/intl.h>
#include "systemFunctions.h"
+#include "globalFunctions.h"
#include "systemConstants.h"
#include "fileTraverser.h"
#include <wx/file.h>
@@ -8,6 +9,8 @@
#include <boost/bind.hpp>
#include <algorithm>
#include <wx/log.h>
+#include <wx/datetime.h>
+#include "stringConv.h"
#ifdef FFS_WIN
#include <wx/msw/wrapwin.h> //includes "windows.h"
@@ -28,21 +31,30 @@ using FreeFileSync::FileError;
Zstring FreeFileSync::getFormattedDirectoryName(const Zstring& dirname)
-{ //Formatting is needed since functions expect the directory to end with '\' to be able to split the relative names.
+{
+ //Formatting is needed since functions expect the directory to end with '\' to be able to split the relative names.
//Also improves usability.
- Zstring dirnameTmp = dirname;
+ wxString dirnameTmp = zToWx(dirname);
dirnameTmp.Trim(true); //remove whitespace characters from right
dirnameTmp.Trim(false); //remove whitespace characters from left
if (dirnameTmp.empty()) //an empty string is interpreted as "\"; this is not desired
return Zstring();
- if (!dirnameTmp.EndsWith(globalFunctions::FILE_NAME_SEPARATOR))
- dirnameTmp += globalFunctions::FILE_NAME_SEPARATOR;
+ if (!dirnameTmp.EndsWith(zToWx(globalFunctions::FILE_NAME_SEPARATOR)))
+ dirnameTmp += zToWx(globalFunctions::FILE_NAME_SEPARATOR);
+
+ //replace macros
+ wxString timeNow = wxDateTime::Now().FormatISOTime();
+ timeNow.Replace(wxT(":"), wxT("-"));
+ dirnameTmp.Replace(wxT("%time%"), timeNow.c_str());
+
+ const wxString dateToday = wxDateTime::Now().FormatISODate();
+ dirnameTmp.Replace(wxT("%date%"), dateToday.c_str());
//don't do directory formatting with wxFileName, as it doesn't respect //?/ - prefix
- return dirnameTmp;
+ return wxToZ(dirnameTmp);
}
@@ -64,7 +76,7 @@ public:
private:
RecycleBin() :
- recycleBinAvailable(false)
+ recycleBinAvailable(false)
{
#ifdef FFS_WIN
recycleBinAvailable = true;
@@ -117,7 +129,8 @@ bool moveToRecycleBin(const Zstring& filename) //throw (std::logic_error)
bool FreeFileSync::fileExists(const DefaultChar* filename)
-{ //symbolic links (broken or not) are also treated as existing files!
+{
+ //symbolic links (broken or not) are also treated as existing files!
#ifdef FFS_WIN
// we must use GetFileAttributes() instead of the ANSI C functions because
// it can cope with network (UNC) paths unlike them
@@ -134,7 +147,8 @@ bool FreeFileSync::fileExists(const DefaultChar* filename)
bool FreeFileSync::dirExists(const DefaultChar* dirname)
-{ //symbolic links (broken or not) are also treated as existing directories!
+{
+ //symbolic links (broken or not) are also treated as existing directories!
#ifdef FFS_WIN
// we must use GetFileAttributes() instead of the ANSI C functions because
// it can cope with network (UNC) paths unlike them
@@ -166,15 +180,15 @@ bool FreeFileSync::symlinkExists(const DefaultChar* objname)
bool FreeFileSync::isMovable(const Zstring& pathFrom, const Zstring& pathTo)
{
- wxLogNull noWxLogs; //prevent wxWidgets logging if dummy file creation failed
+ wxLogNull noWxLogs; //prevent wxWidgets logging if dummy file creation failed
const Zstring dummyFileSource = pathFrom.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ?
- pathFrom + wxT("DeleteMe.tmp") :
- pathFrom + globalFunctions::FILE_NAME_SEPARATOR + wxT("DeleteMe.tmp");
+ pathFrom + DefaultStr("DeleteMe.tmp") :
+ pathFrom + globalFunctions::FILE_NAME_SEPARATOR + DefaultStr("DeleteMe.tmp");
const Zstring dummyFileTarget = pathTo.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ?
- pathTo + wxT("DeleteMe.tmp") :
- pathTo + globalFunctions::FILE_NAME_SEPARATOR + wxT("DeleteMe.tmp");
+ pathTo + DefaultStr("DeleteMe.tmp") :
+ pathTo + globalFunctions::FILE_NAME_SEPARATOR + DefaultStr("DeleteMe.tmp");
try
{
removeFile(dummyFileSource, false);
@@ -184,7 +198,7 @@ bool FreeFileSync::isMovable(const Zstring& pathFrom, const Zstring& pathTo)
//create dummy file
{
- wxFile dummy(dummyFileSource.c_str(), wxFile::write);
+ wxFile dummy(zToWx(dummyFileSource), wxFile::write);
if (!dummy.IsOpened())
return false; //if there's no write access, files can't be moved neither
dummy.Write(wxT("FreeFileSync dummy file. May be deleted safely.\n"));
@@ -195,7 +209,7 @@ bool FreeFileSync::isMovable(const Zstring& pathFrom, const Zstring& pathTo)
#ifdef FFS_WIN
::MoveFileEx(dummyFileSource.c_str(), //__in LPCTSTR lpExistingFileName,
dummyFileTarget.c_str(), //__in_opt LPCTSTR lpNewFileName,
- 0) != 0; //__in DWORD dwFlags
+ 0) != 0; //__in DWORD dwFlags
#elif defined FFS_LINUX
::rename(dummyFileSource.c_str(), dummyFileTarget.c_str()) == 0;
#endif
@@ -227,7 +241,7 @@ void FreeFileSync::removeFile(const Zstring& filename, const bool useRecycleBin)
if (useRecycleBin)
{
if (!moveToRecycleBin(filename))
- throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + filename.c_str() + wxT("\""));
+ throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + zToWx(filename) + wxT("\""));
return;
}
@@ -237,20 +251,20 @@ void FreeFileSync::removeFile(const Zstring& filename, const bool useRecycleBin)
filename.c_str(), //address of filename
FILE_ATTRIBUTE_NORMAL)) //attributes to set
{
- wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + filename.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
//remove file, support for \\?\-prefix
if (!::DeleteFile(filename.c_str()))
{
- wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + filename.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
#elif defined FFS_LINUX
if (::unlink(filename.c_str()) != 0)
{
- wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + filename.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error deleting file:")) + wxT("\n\"") + zToWx(filename) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
#endif
@@ -286,7 +300,8 @@ void FreeFileSync::moveFile(const Zstring& sourceFile, const Zstring& targetFile
{
if (fileExists(targetFile.c_str())) //test file existence: e.g. Linux might silently overwrite existing symlinks
{
- const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + sourceFile + wxT("\" ->\n\"") + targetFile + wxT("\"");
+ const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") +
+ zToWx(targetFile) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + _("Target file already existing!"));
}
@@ -303,7 +318,8 @@ void FreeFileSync::moveFile(const Zstring& sourceFile, const Zstring& targetFile
const DWORD lastError = ::GetLastError();
if (lastError != ERROR_NOT_SAME_DEVICE)
{
- const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\"");
+ const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") +
+ zToWx(targetFile) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError));
}
@@ -318,14 +334,15 @@ void FreeFileSync::moveFile(const Zstring& sourceFile, const Zstring& targetFile
#elif defined FFS_LINUX
//first try to move the file directly without copying
- if (rename(sourceFile.c_str(), targetFile.c_str()) == 0)
+ if (::rename(sourceFile.c_str(), targetFile.c_str()) == 0)
return;
//if moving failed treat as error (except when it tried to move to a different volume: in this case we will copy the file)
if (errno != EXDEV)
{
- const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\"");
- throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(errno));
+ const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") +
+ zToWx(targetFile) + wxT("\"");
+ throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
//file is on a different volume: let's copy it
@@ -349,8 +366,8 @@ public:
typedef std::vector<std::pair<Zstring, Zstring> > NamePair;
TraverseOneLevel(NamePair& filesShort, NamePair& dirsShort) :
- m_files(filesShort),
- m_dirs(dirsShort) {}
+ m_files(filesShort),
+ m_dirs(dirsShort) {}
virtual ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details)
{
@@ -375,19 +392,22 @@ private:
void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback) //throw (FileError);
{
+ using namespace FreeFileSync;
+
//handle symbolic links
- if (FreeFileSync::symlinkExists(sourceDir))
+ if (symlinkExists(sourceDir))
{
- FreeFileSync::createDirectory(targetDir, sourceDir, true); //copy symbolic link
- FreeFileSync::removeDirectory(sourceDir, false); //if target is already another symlink or directory, sourceDir-symlink is silently deleted
+ createDirectory(targetDir, sourceDir, true); //copy symbolic link
+ removeDirectory(sourceDir, false); //if target is already another symlink or directory, sourceDir-symlink is silently deleted
return;
}
- if (FreeFileSync::dirExists(targetDir))
+ if (dirExists(targetDir))
{
if (!ignoreExistingDirs) //directory or symlink exists
{
- const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + sourceDir + wxT("\" ->\n\"") + targetDir + wxT("\"");
+ const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") +
+ zToWx(sourceDir) + wxT("\" ->\n\"") + zToWx(targetDir) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + _("Target directory already existing!"));
}
}
@@ -404,7 +424,8 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool
const DWORD lastError = ::GetLastError();
if (lastError != ERROR_NOT_SAME_DEVICE)
{
- const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\" ->\n\"") + targetDir.c_str() + wxT("\"");
+ const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + zToWx(sourceDir) + wxT("\" ->\n\"") +
+ zToWx(targetDir) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError));
}
#elif defined FFS_LINUX
@@ -414,13 +435,14 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool
//if moving failed treat as error (except when it tried to move to a different volume: in this case we will copy the directory)
if (errno != EXDEV)
{
- const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\" ->\n\"") + targetDir.c_str() + wxT("\"");
- throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(errno));
+ const wxString errorMessage = wxString(_("Error moving directory:")) + wxT("\n\"") +
+ zToWx(sourceDir) + wxT("\" ->\n\"") + zToWx(targetDir) + wxT("\"");
+ throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
#endif
//create target
- FreeFileSync::createDirectory(targetDir, sourceDir, false); //throw (FileError);
+ createDirectory(targetDir, sourceDir, false); //throw (FileError);
}
//call back once per folder
@@ -431,8 +453,8 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool
break;
case MoveFileCallback::CANCEL:
//an user aborted operation IS an error condition!
- throw FileError(wxString(_("Error moving directory:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\" ->\n\"") +
- targetDir.c_str() + wxT("\"") + wxT("\n\n") + _("Operation aborted!"));
+ throw FileError(wxString(_("Error moving directory:")) + wxT("\n\"") + zToWx(sourceDir) + wxT("\" ->\n\"") +
+ zToWx(targetDir) + wxT("\"") + wxT("\n\n") + _("Operation aborted!"));
}
//move files/folders recursively
@@ -441,7 +463,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool
//traverse source directory one level
TraverseOneLevel traverseCallback(fileList, dirList);
- FreeFileSync::traverseFolder(sourceDir, false, &traverseCallback); //traverse one level
+ traverseFolder(sourceDir, false, &traverseCallback); //traverse one level
const Zstring targetDirFormatted = targetDir.EndsWith(globalFunctions::FILE_NAME_SEPARATOR) ? //ends with path separator
targetDir :
@@ -458,9 +480,7 @@ void moveDirectoryImpl(const Zstring& sourceDir, const Zstring& targetDir, bool
//attention: if move-operation was cancelled an exception is thrown => sourceDir is not deleted, as we wish!
//delete source
- FreeFileSync::removeDirectory(sourceDir, false); //throw (FileError);
-
- return;
+ removeDirectory(sourceDir, false); //throw (FileError);
}
@@ -488,8 +508,8 @@ class FilesDirsOnlyTraverser : public FreeFileSync::TraverseCallback
{
public:
FilesDirsOnlyTraverser(std::vector<Zstring>& files, std::vector<Zstring>& dirs) :
- m_files(files),
- m_dirs(dirs) {}
+ m_files(files),
+ m_dirs(dirs) {}
virtual ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details)
{
@@ -529,7 +549,7 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc
if (useRecycleBin)
{
if (!moveToRecycleBin(directory))
- throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + directory.c_str() + wxT("\""));
+ throw FileError(wxString(_("Error moving to Recycle Bin:")) + wxT("\n\"") + zToWx(directory) + wxT("\""));
return;
}
@@ -561,7 +581,7 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc
{
if (::unlink(directory.c_str()) != 0)
{
- wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
return;
@@ -585,17 +605,13 @@ void FreeFileSync::removeDirectory(const Zstring& directory, const bool useRecyc
#ifdef FFS_WIN
//remove directory, support for \\?\-prefix
if (!::RemoveDirectory(directory.c_str()))
- {
- wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"");
- throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
- }
#else
if (::rmdir(directory.c_str()) != 0)
+#endif
{
- wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error deleting directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
-#endif
}
@@ -697,8 +713,8 @@ public:
private:
KernelDllHandler() :
- getFinalPathNameByHandle(NULL),
- hKernel(NULL)
+ getFinalPathNameByHandle(NULL),
+ hKernel(NULL)
{
//get a handle to the DLL module containing required functionality
hKernel = ::LoadLibrary(wxT("kernel32.dll"));
@@ -748,50 +764,49 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa
return targetPath;
}
-
+//#warning teste
//#include <aclapi.h>
-//optionally: copy additional metadata, DO NOTHING if something fails
+////optionally: copy additional metadata, DO NOTHING if something fails
//void copyAdditionalMetadata(const Zstring& sourceDir, const Zstring& targetDir)
//{
+// //copy NTFS permissions
+//
// PSECURITY_DESCRIPTOR pSD;
//
-// PSID pSidOwner;
-// PSID pSidGroup;
// PACL pDacl;
-// PACL pSacl;
// if (::GetNamedSecurityInfo(
// const_cast<DefaultChar*>(sourceDir.c_str()),
// SE_FILE_OBJECT, //file or directory
-// OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
-// &pSidOwner,
-// &pSidGroup,
+// DACL_SECURITY_INFORMATION,
+// NULL,
+// NULL,
// &pDacl,
-// &pSacl,
+// NULL,
// &pSD
// ) == ERROR_SUCCESS)
// {
// //(try to) set new security information
// if (::SetNamedSecurityInfo(
-// const_cast<DefaultChar*>(targetDir.c_str()),
-// SE_FILE_OBJECT, //file or directory
-// OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
-// pSidOwner,
-// pSidGroup,
-// pDacl,
-// pSacl) != ERROR_SUCCESS) //return value not evalutated!
-// {
+// const_cast<DefaultChar*>(targetDir.c_str()),
+// SE_FILE_OBJECT, //file or directory
+// DACL_SECURITY_INFORMATION,
+// NULL,
+// NULL,
+// pDacl,
+// NULL) != ERROR_SUCCESS) //return value not evalutated!
+// {
// const wxString errorMessage = wxString(wxT("Error 2:")) + wxT("\n\"") + targetDir.c_str() + wxT("\"");
// throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
// }
-//warning BUG!
//
-// LocalFree(pSD); //pSidOwner, pSidGroup, pDacl, pSacl must not be freed!
+//#warning BUG!
+// LocalFree(pSD);
// }
// else
-// {
-// const wxString errorMessage = wxString(wxT("Error 1:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\"");
-// throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
-// }
+// {
+// const wxString errorMessage = wxString(wxT("Error 1:")) + wxT("\n\"") + sourceDir.c_str() + wxT("\"");
+// throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+// }
//
//}
#endif
@@ -799,6 +814,8 @@ Zstring resolveDirectorySymlink(const Zstring& dirLinkName) //get full target pa
void createDirectoryRecursively(const Zstring& directory, const Zstring& templateDir, const bool copyDirectorySymLinks, const int level)
{
+ using namespace FreeFileSync;
+
if (FreeFileSync::dirExists(directory))
return;
@@ -882,7 +899,7 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat
const int bytesWritten = readlink(templateDir.c_str(), buffer, BUFFER_SIZE);
if (bytesWritten < 0 || bytesWritten == BUFFER_SIZE)
{
- wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + templateDir.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zToWx(templateDir) + wxT("\"");
if (bytesWritten < 0) errorMessage += wxString(wxT("\n\n")) + FreeFileSync::getLastErrorFormatted();
throw FileError(errorMessage);
}
@@ -891,7 +908,7 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat
if (symlink(buffer, directory.c_str()) != 0)
{
- wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
return; //symlink created successfully
@@ -899,9 +916,9 @@ void createDirectoryRecursively(const Zstring& directory, const Zstring& templat
}
//default directory creation
- if (mkdir(directory.c_str(), 0755) != 0 && level == 0)
+ if (::mkdir(directory.c_str(), 0755) != 0 && level == 0)
{
- wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error creating directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
@@ -944,6 +961,24 @@ void FreeFileSync::createDirectory(const Zstring& directory, const Zstring& temp
}
+Zstring createTempName(const Zstring& filename)
+{
+ Zstring output = filename + DefaultStr(".tmp");
+
+ //ensure uniqueness
+ if (FreeFileSync::fileExists(output))
+ {
+ //if it's not unique, add a postfix number
+ int postfix = 1;
+ while (FreeFileSync::fileExists(output + DefaultChar('_') + numberToZstring(postfix)))
+ ++postfix;
+
+ output += DefaultChar('_') + numberToZstring(postfix);
+ }
+ return output;
+}
+
+
#ifdef FFS_WIN
#ifndef COPY_FILE_COPY_SYMLINK
@@ -1011,8 +1046,8 @@ bool supportForSymbolicLinks()
void FreeFileSync::copyFile(const Zstring& sourceFile,
const Zstring& targetFile,
const bool copyFileSymLinks,
- ShadowCopy* shadowCopyHandler,
- CopyFileCallback* callback)
+ FreeFileSync::ShadowCopy* shadowCopyHandler,
+ FreeFileSync::CopyFileCallback* callback)
{
DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS;
@@ -1021,9 +1056,10 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
if (copyFileSymLinks && symlinksSupported)
copyFlags |= COPY_FILE_COPY_SYMLINK;
+ const Zstring temporary = createTempName(targetFile); //use temporary file until a correct date has been set
if (!::CopyFileEx( //same performance as CopyFile()
sourceFile.c_str(),
- targetFile.c_str(),
+ temporary.c_str(),
copyCallbackInternal,
callback,
NULL,
@@ -1039,17 +1075,26 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
lastError == ERROR_LOCK_VIOLATION))
{
const Zstring shadowFilename(shadowCopyHandler->makeShadowCopy(sourceFile));
- FreeFileSync::copyFile(shadowFilename, //transferred bytes is automatically reset when new file is copied
- targetFile,
- copyFileSymLinks,
- NULL,
- callback);
+ copyFile(shadowFilename, //transferred bytes is automatically reset when new file is copied
+ targetFile,
+ copyFileSymLinks,
+ NULL,
+ callback);
return;
}
const wxString errorMessage = wxString(_("Error copying file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError));
}
+
+ //rename temporary file
+ if (!::MoveFileEx(temporary.c_str(), //__in LPCTSTR lpExistingFileName,
+ targetFile.c_str(), //__in_opt LPCTSTR lpNewFileName,
+ 0)) //__in DWORD dwFlags
+ {
+ const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + temporary + wxT("\" ->\n\"") + targetFile + wxT("\"");
+ throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+ }
}
@@ -1079,7 +1124,7 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
using FreeFileSync::CopyFileCallback;
if (FreeFileSync::fileExists(targetFile.c_str()))
- throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") + targetFile.c_str() + wxT("\"\n\n")
+ throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") + zToWx(targetFile) + wxT("\"\n\n")
+ _("Target file already existing!"));
//symbolic link handling
@@ -1089,7 +1134,7 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
struct stat linkInfo;
if (lstat(sourceFile.c_str(), &linkInfo) != 0)
{
- const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\"");
+ const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
@@ -1101,7 +1146,7 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
const int bytesWritten = readlink(sourceFile.c_str(), buffer, BUFFER_SIZE);
if (bytesWritten < 0 || bytesWritten == BUFFER_SIZE)
{
- wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error resolving symbolic link:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"");
if (bytesWritten < 0) errorMessage += wxString(wxT("\n\n")) + FreeFileSync::getLastErrorFormatted();
throw FileError(errorMessage);
}
@@ -1110,7 +1155,7 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
if (symlink(buffer, targetFile.c_str()) != 0)
{
- const wxString errorMessage = wxString(_("Error writing file:")) + wxT("\n\"") + targetFile.c_str() + wxT("\"");
+ const wxString errorMessage = wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
@@ -1122,19 +1167,21 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
struct stat fileInfo;
if (stat(sourceFile.c_str(), &fileInfo) != 0) //read file attributes from source file (resolving symlinks; but cannot be one in this context)
{
- const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\"");
+ const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
//open sourceFile for reading
std::ifstream fileIn(sourceFile.c_str(), std::ios_base::binary);
if (fileIn.fail())
- throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\""));
+ throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\""));
//create targetFile and open it for writing
- std::ofstream fileOut(targetFile.c_str(), std::ios_base::binary);
+ const Zstring temporary = createTempName(targetFile); //use temporary file until a correct date has been set
+
+ std::ofstream fileOut(temporary.c_str(), std::ios_base::binary);
if (fileOut.fail())
- throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + targetFile.c_str() + wxT("\""));
+ throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\""));
try
{
@@ -1148,16 +1195,16 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
{
fileOut.write(memory.buffer, fileIn.gcount());
if (fileOut.bad())
- throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + targetFile.c_str() + wxT("\""));
+ throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\""));
break;
}
else if (fileIn.fail())
- throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\""));
+ throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\""));
fileOut.write(memory.buffer, memory.bufferSize);
if (fileOut.bad())
- throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + targetFile.c_str() + wxT("\""));
+ throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\""));
totalBytesTransferred += memory.bufferSize;
@@ -1171,8 +1218,8 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
case CopyFileCallback::CANCEL:
//an user aborted operation IS an error condition!
- throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + sourceFile.c_str() + wxT("\" ->\n\"") +
- targetFile.c_str() + wxT("\"\n\n") + _("Operation aborted!"));
+ throw FileError(wxString(_("Error copying file:")) + wxT("\n\"") + zToWx(sourceFile) + wxT("\" ->\n\"") +
+ zToWx(targetFile) + wxT("\"\n\n") + _("Operation aborted!"));
}
}
}
@@ -1183,25 +1230,35 @@ void FreeFileSync::copyFile(const Zstring& sourceFile,
//adapt file modification time:
struct utimbuf newTimes;
- time(&newTimes.actime); //set file access time to current time
+ ::time(&newTimes.actime); //set file access time to current time
newTimes.modtime = fileInfo.st_mtime;
- if (utime(targetFile.c_str(), &newTimes) != 0)
+ if (utime(temporary.c_str(), &newTimes) != 0)
{
- wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + targetFile.c_str() + wxT("\"");
+ wxString errorMessage = wxString(_("Error changing modification time:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"");
+ throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+ }
+
+ //rename temporary file
+ if (::rename(temporary.c_str(), targetFile.c_str()) != 0)
+ {
+ const wxString errorMessage = wxString(_("Error moving file:")) + wxT("\n\"") + zToWx(temporary) + wxT("\" ->\n\"") + zToWx(targetFile) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
//set file access rights
- if (chmod(targetFile.c_str(), fileInfo.st_mode) != 0)
+ if (::chmod(targetFile.c_str(), fileInfo.st_mode) != 0)
{
- wxString errorMessage = wxString(_("Error writing file attributes:")) + wxT("\n\"") + targetFile.c_str() + wxT("\"");
+ const wxString errorMessage = wxString(_("Error writing file attributes:")) + wxT("\n\"") + zToWx(targetFile) + wxT("\"");
throw FileError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
}
}
catch (...)
- { //try to delete target file if error occured, or exception was thrown in callback function
+ {
+ //try to delete target file if error occured, or exception was thrown in callback function
if (FreeFileSync::fileExists(targetFile))
::unlink(targetFile); //don't handle error situations!
+ if (FreeFileSync::fileExists(temporary))
+ ::unlink(temporary); //don't handle error situations!
throw;
}
diff --git a/shared/fileHandling.h b/shared/fileHandling.h
index 5ccd595f..d856603f 100644
--- a/shared/fileHandling.h
+++ b/shared/fileHandling.h
@@ -8,76 +8,74 @@
namespace FreeFileSync
{
- Zstring getFormattedDirectoryName(const Zstring& dirname);
+Zstring getFormattedDirectoryName(const Zstring& dirname);
- bool fileExists(const DefaultChar* filename); //throw() replaces wxFileExists()!
- bool dirExists(const DefaultChar* dirname); //throw() replaces wxDirExists(): optional 'cause wxDirExists treats symlinks correctly
- bool symlinkExists(const DefaultChar* objname); //throw() check if a symbolic link exists
+bool fileExists(const DefaultChar* filename); //throw() replaces wxFileExists()!
+bool dirExists(const DefaultChar* dirname); //throw() replaces wxDirExists(): optional 'cause wxDirExists treats symlinks correctly
+bool symlinkExists(const DefaultChar* objname); //throw() check if a symbolic link exists
- //check if files can be moved between two EXISTING paths (without copying)
- bool isMovable(const Zstring& pathFrom, const Zstring& pathTo); //throw()
+//check if files can be moved between two EXISTING paths (without copying)
+bool isMovable(const Zstring& pathFrom, const Zstring& pathTo); //throw()
- //optionally: copy directory last change date, DOES NOTHING if something fails
- void copyDirLastChangeDate(const Zstring& sourceDir, const Zstring& targetDir);
+//optionally: copy directory last change date, DOES NOTHING if something fails
+void copyDirLastChangeDate(const Zstring& sourceDir, const Zstring& targetDir);
- //recycler
- bool recycleBinExists(); //test existence of Recycle Bin API on current system
+//recycler
+bool recycleBinExists(); //test existence of Recycle Bin API on current system
- //file handling
- void removeFile(const Zstring& filename, const bool useRecycleBin); //throw (FileError, std::logic_error)
- void removeDirectory(const Zstring& directory, const bool useRecycleBin); //throw (FileError)
+//file handling
+void removeFile(const Zstring& filename, const bool useRecycleBin); //throw (FileError, std::logic_error)
+void removeDirectory(const Zstring& directory, const bool useRecycleBin); //throw (FileError)
- class MoveFileCallback //callback functionality
+struct MoveFileCallback //callback functionality
+{
+ virtual ~MoveFileCallback() {}
+
+ enum Response
{
- public:
- virtual ~MoveFileCallback() {}
-
- enum Response
- {
- CONTINUE,
- CANCEL
- };
- virtual Response requestUiRefresh() = 0; //DON'T throw exceptions here, at least in Windows build!
+ CONTINUE,
+ CANCEL
};
+ virtual Response requestUiRefresh() = 0; //DON'T throw exceptions here, at least in Windows build!
+};
- //move source to target; expectations: target not existing, all super-directories of target exist
- void moveFile(const Zstring& sourceFile, const Zstring& targetFile, MoveFileCallback* callback = NULL); //throw (FileError);
+//move source to target; expectations: target not existing, all super-directories of target exist
+void moveFile(const Zstring& sourceFile, const Zstring& targetFile, MoveFileCallback* callback = NULL); //throw (FileError);
- //move source to target including subdirectories
- //"ignoreExistingDirs": existing directories will be enhanced as long as this is possible without overwriting files
- void moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback = NULL); //throw (FileError);
+//move source to target including subdirectories
+//"ignoreExistingDirs": existing directories will be enhanced as long as this is possible without overwriting files
+void moveDirectory(const Zstring& sourceDir, const Zstring& targetDir, bool ignoreExistingDirs, MoveFileCallback* callback = NULL); //throw (FileError);
- //creates superdirectories automatically:
- void createDirectory(const Zstring& directory, const Zstring& templateDir = Zstring(), const bool copyDirectorySymLinks = false); //throw (FileError);
+//creates superdirectories automatically:
+void createDirectory(const Zstring& directory, const Zstring& templateDir = Zstring(), const bool copyDirectorySymLinks = false); //throw (FileError);
+
+struct CopyFileCallback //callback functionality
+{
+ virtual ~CopyFileCallback() {}
- class CopyFileCallback //callback functionality
+ enum Response
{
- public:
- virtual ~CopyFileCallback() {}
-
- enum Response
- {
- CONTINUE,
- CANCEL
- };
- virtual Response updateCopyStatus(const wxULongLong& totalBytesTransferred) = 0; //DON'T throw exceptions here, at least in Windows build!
+ CONTINUE,
+ CANCEL
};
+ virtual Response updateCopyStatus(const wxULongLong& totalBytesTransferred) = 0; //DON'T throw exceptions here, at least in Windows build!
+};
#ifdef FFS_WIN
- class ShadowCopy;
+class ShadowCopy;
- void copyFile(const Zstring& sourceFile,
- const Zstring& targetFile,
- const bool copyFileSymLinks,
- ShadowCopy* shadowCopyHandler = NULL, //supply handler for making shadow copies
- CopyFileCallback* callback = NULL); //throw (FileError);
+void copyFile(const Zstring& sourceFile,
+ const Zstring& targetFile,
+ const bool copyFileSymLinks,
+ ShadowCopy* shadowCopyHandler = NULL, //supply handler for making shadow copies
+ CopyFileCallback* callback = NULL); //throw (FileError);
#elif defined FFS_LINUX
- void copyFile(const Zstring& sourceFile,
- const Zstring& targetFile,
- const bool copyFileSymLinks,
- CopyFileCallback* callback = NULL); //throw (FileError);
+void copyFile(const Zstring& sourceFile,
+ const Zstring& targetFile,
+ const bool copyFileSymLinks,
+ CopyFileCallback* callback = NULL); //throw (FileError);
#endif
}
diff --git a/shared/fileTraverser.cpp b/shared/fileTraverser.cpp
index ab223791..c323f1a3 100644
--- a/shared/fileTraverser.cpp
+++ b/shared/fileTraverser.cpp
@@ -2,6 +2,7 @@
#include "systemConstants.h"
#include "systemFunctions.h"
#include <wx/intl.h>
+#include "stringConv.h"
#ifdef FFS_WIN
#include <wx/msw/wrapwin.h> //includes "windows.h"
@@ -108,11 +109,11 @@ private:
template <bool traverseDirectorySymlinks>
bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback* sink, const int level)
{
- using FreeFileSync::TraverseCallback;
+ using namespace FreeFileSync;
if (level == 100) //catch endless recursion
{
- switch (sink->onError(wxString(_("Endless loop when traversing directory:")) + wxT("\n\"") + directory + wxT("\"")))
+ switch (sink->onError(wxString(_("Endless loop when traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"")))
{
case TraverseCallback::TRAVERSING_STOP:
return false;
@@ -139,7 +140,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback*
return true;
//else: we have a problem... report it:
- const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"") ;
+ const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ;
switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError)))
{
case TraverseCallback::TRAVERSING_STOP:
@@ -151,7 +152,8 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback*
CloseFindHandleOnExit dummy(searchHandle);
do
- { //don't return "." and ".."
+ {
+ //don't return "." and ".."
const wxChar* const shortName = fileMetaData.cFileName;
if ( shortName[0] == wxChar('.') &&
((shortName[1] == wxChar('.') && shortName[2] == wxChar('\0')) ||
@@ -211,7 +213,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback*
return true; //everything okay
//else: we have a problem... report it:
- const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"") ;
+ const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ;
switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted(lastError)))
{
case TraverseCallback::TRAVERSING_STOP:
@@ -224,7 +226,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback*
DIR* dirObj = ::opendir(directory.c_str()); //directory must NOT end with path separator, except "/"
if (dirObj == NULL)
{
- const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"") ;
+ const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ;
switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()))
{
case TraverseCallback::TRAVERSING_STOP:
@@ -245,7 +247,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback*
return true; //everything okay
//else: we have a problem... report it:
- const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + directory.c_str() + wxT("\"") ;
+ const wxString errorMessage = wxString(_("Error traversing directory:")) + wxT("\n\"") + zToWx(directory) + wxT("\"") ;
switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()))
{
case TraverseCallback::TRAVERSING_STOP:
@@ -256,7 +258,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback*
}
//don't return "." and ".."
- const wxChar* const shortName = dirEntry->d_name;
+ const DefaultChar* const shortName = dirEntry->d_name;
if ( shortName[0] == wxChar('.') &&
((shortName[1] == wxChar('.') && shortName[2] == wxChar('\0')) ||
shortName[1] == wxChar('\0')))
@@ -269,7 +271,7 @@ bool traverseDirectory(const Zstring& directory, FreeFileSync::TraverseCallback*
struct stat fileInfo;
if (lstat(fullName.c_str(), &fileInfo) != 0) //lstat() does not resolve symlinks
{
- const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + fullName.c_str() + wxT("\"");
+ const wxString errorMessage = wxString(_("Error reading file attributes:")) + wxT("\n\"") + zToWx(fullName) + wxT("\"");
switch (sink->onError(errorMessage + wxT("\n\n") + FreeFileSync::getLastErrorFormatted()))
{
case TraverseCallback::TRAVERSING_STOP:
diff --git a/shared/fileTraverser.h b/shared/fileTraverser.h
index d2aa7f3e..c1277d87 100644
--- a/shared/fileTraverser.h
+++ b/shared/fileTraverser.h
@@ -10,55 +10,55 @@
namespace FreeFileSync
{
- class TraverseCallback
- {
- public:
- virtual ~TraverseCallback() {}
-
- enum ReturnValue
- {
- TRAVERSING_STOP,
- TRAVERSING_CONTINUE
- };
+class TraverseCallback
+{
+public:
+ virtual ~TraverseCallback() {}
- struct FileInfo
- {
- wxULongLong fileSize; //unit: bytes!
- wxLongLong lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC
- };
+ enum ReturnValue
+ {
+ TRAVERSING_STOP,
+ TRAVERSING_CONTINUE
+ };
- class ReturnValDir
- {
- public:
- //some proxy classes
- class Stop {};
- class Ignore {};
- class Continue {};
+ struct FileInfo
+ {
+ wxULongLong fileSize; //unit: bytes!
+ wxLongLong lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC
+ };
- ReturnValDir(const Stop&) : returnCode(TRAVERSING_STOP), subDirCb(NULL) {}
- ReturnValDir(const Ignore&) : returnCode(TRAVERSING_IGNORE_DIR), subDirCb(NULL) {}
- ReturnValDir(const Continue&, TraverseCallback* subDirCallback) : returnCode(TRAVERSING_CONTINUE), subDirCb(subDirCallback) {}
+ class ReturnValDir
+ {
+ public:
+ //some proxy classes
+ class Stop {};
+ class Ignore {};
+ class Continue {};
+ ReturnValDir(const Stop&) : returnCode(TRAVERSING_STOP), subDirCb(NULL) {}
+ ReturnValDir(const Ignore&) : returnCode(TRAVERSING_IGNORE_DIR), subDirCb(NULL) {}
+ ReturnValDir(const Continue&, TraverseCallback* subDirCallback) : returnCode(TRAVERSING_CONTINUE), subDirCb(subDirCallback) {}
- enum ReturnValueEnh
- {
- TRAVERSING_STOP,
- TRAVERSING_IGNORE_DIR,
- TRAVERSING_CONTINUE
- };
- const ReturnValueEnh returnCode;
- TraverseCallback* const subDirCb;
+ enum ReturnValueEnh
+ {
+ TRAVERSING_STOP,
+ TRAVERSING_IGNORE_DIR,
+ TRAVERSING_CONTINUE
};
- //overwrite these virtual methods
- virtual ReturnValue onError(const wxString& errorText) = 0;
- virtual ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details) = 0;
- virtual ReturnValDir onDir(const DefaultChar* shortName, const Zstring& fullName) = 0;
+ const ReturnValueEnh returnCode;
+ TraverseCallback* const subDirCb;
};
- //custom traverser with detail information about files
- void traverseFolder(const Zstring& directory, const bool traverseDirectorySymlinks, TraverseCallback* sink); //throw()
+ //overwrite these virtual methods
+ virtual ReturnValue onError(const wxString& errorText) = 0;
+ virtual ReturnValue onFile(const DefaultChar* shortName, const Zstring& fullName, const FileInfo& details) = 0;
+ virtual ReturnValDir onDir(const DefaultChar* shortName, const Zstring& fullName) = 0;
+};
+
+//custom traverser with detail information about files
+void traverseFolder(const Zstring& directory, const bool traverseDirectorySymlinks, TraverseCallback* sink); //throw()
}
#endif // FILETRAVERSER_H_INCLUDED
diff --git a/shared/globalFunctions.cpp b/shared/globalFunctions.cpp
index f50a3097..a5ebba68 100644
--- a/shared/globalFunctions.cpp
+++ b/shared/globalFunctions.cpp
@@ -1,49 +1,11 @@
#include "globalFunctions.h"
#include <wx/msgdlg.h>
#include <wx/file.h>
-#include <fstream>
-#include <wx/stream.h>
#include <wx/stopwatch.h>
#include <cmath>
#include "systemConstants.h"
-wxString globalFunctions::numberToWxString(const unsigned int number)
-{
- return wxString::Format(wxT("%u"), number);
-}
-
-
-wxString globalFunctions::numberToWxString(const int number)
-{
- return wxString::Format(wxT("%i"), number);
-}
-
-
-wxString globalFunctions::numberToWxString(const float number)
-{
- return wxString::Format(wxT("%f"), number);
-}
-
-
-int globalFunctions::stringToInt(const std::string& number)
-{
- return atoi(number.c_str());
-}
-
-
-long globalFunctions::stringToLong(const std::string& number)
-{
- return atol(number.c_str());
-}
-
-
-double globalFunctions::stringToDouble(const std::string& number)
-{
- return atof(number.c_str());
-}
-
-
int globalFunctions::wxStringToInt(const wxString& number)
{
long result = 0;
@@ -70,42 +32,10 @@ unsigned int globalFunctions::getDigitCount(const unsigned int number) //count n
}
-int globalFunctions::readInt(std::ifstream& stream)
-{
- int result = 0;
- char* buffer = reinterpret_cast<char*>(&result);
- stream.read(buffer, sizeof(int));
- return result;
-}
-
-
-void globalFunctions::writeInt(std::ofstream& stream, const int number)
-{
- const char* buffer = reinterpret_cast<const char*>(&number);
- stream.write(buffer, sizeof(int));
-}
-
-
-int globalFunctions::readInt(wxInputStream& stream)
-{
- int result = 0;
- char* buffer = reinterpret_cast<char*>(&result);
- stream.Read(buffer, sizeof(int));
- return result;
-}
-
-
-void globalFunctions::writeInt(wxOutputStream& stream, const int number)
-{
- const char* buffer = reinterpret_cast<const char*>(&number);
- stream.Write(buffer, sizeof(int));
-}
-
-
//############################################################################
Performance::Performance() :
- resultWasShown(false),
- timer(new wxStopWatch)
+ resultWasShown(false),
+ timer(new wxStopWatch)
{
timer->Start();
}
@@ -128,8 +58,8 @@ void Performance::showResult()
//############################################################################
DebugLog::DebugLog() :
- lineCount(0),
- logFile(NULL)
+ lineCount(0),
+ logFile(NULL)
{
logFile = new wxFile;
logfileName = assembleFileName();
diff --git a/shared/globalFunctions.h b/shared/globalFunctions.h
index b53ba596..74387959 100644
--- a/shared/globalFunctions.h
+++ b/shared/globalFunctions.h
@@ -9,6 +9,8 @@
#include <wx/longlong.h>
#include <memory>
#include <sstream>
+#include <fstream>
+#include <wx/stream.h>
class wxInputStream;
class wxOutputStream;
@@ -20,129 +22,131 @@ namespace globalFunctions
//------------------------------------------------
// FUNCTIONS
//------------------------------------------------
- inline
- int round(double d) //little rounding function
- {
- return static_cast<int>(d < 0 ? d - .5 : d + .5);
- }
+inline
+int round(double d) //little rounding function
+{
+ return static_cast<int>(d < 0 ? d - .5 : d + .5);
+}
- template <class T>
- inline
- T abs(const T& d) //absolute value
- {
- return(d < 0 ? -d : d);
- }
+template <class T>
+inline
+T abs(const T& d) //absolute value
+{
+ return(d < 0 ? -d : d);
+}
- template <class T>
- inline std::string numberToString(const T& number) //convert number to string the C++ way
- {
- std::stringstream ss;
- ss << number;
- return ss.str();
- }
+template <class T>
+inline
+std::string numberToString(const T& number) //convert number to string the C++ way
+{
+ std::stringstream ss;
+ ss << number;
+ return ss.str();
+}
- wxString numberToWxString(const unsigned int number); //convert number to wxString
- wxString numberToWxString(const int number); //convert number to wxString
- wxString numberToWxString(const float number); //convert number to wxString
+wxString numberToWxString(const unsigned int number); //convert number to wxString
+wxString numberToWxString(const int number); //convert number to wxString
+wxString numberToWxString(const float number); //convert number to wxString
- int stringToInt( const std::string& number); //convert String to number
- long stringToLong( const std::string& number); //convert String to number
- double stringToDouble(const std::string& number); //convert String to number
+int stringToInt( const std::string& number); //convert String to number
+long stringToLong( const std::string& number); //convert String to number
+double stringToDouble(const std::string& number); //convert String to number
- int wxStringToInt( const wxString& number); //convert wxString to number
- double wxStringToDouble(const wxString& number); //convert wxString to number
+int wxStringToInt( const wxString& number); //convert wxString to number
+double wxStringToDouble(const wxString& number); //convert wxString to number
- unsigned int getDigitCount(const unsigned int number); //count number of digits
+unsigned int getDigitCount(const unsigned int number); //count number of digits
- int readInt(std::ifstream& stream); //read int from file stream
- void writeInt(std::ofstream& stream, const int number); //write int to filestream
+//read/write numbers: int, long, unsigned int ... ect
+template <class T> T readNumber(std::ifstream& stream);
+template <class T> void writeNumber(std::ofstream& stream, T number);
- int readInt(wxInputStream& stream); //read int from file stream
- void writeInt(wxOutputStream& stream, const int number); //write int to filestream
+template <class T> T readNumber(wxInputStream& stream);
+template <class T> void writeNumber(wxOutputStream& stream, T number);
- inline
- wxLongLong convertToSigned(const wxULongLong number)
- {
- return wxLongLong(number.GetHi(), number.GetLo());
- }
+inline
+wxLongLong convertToSigned(const wxULongLong number)
+{
+ return wxLongLong(number.GetHi(), number.GetLo());
+}
//Note: the following lines are a performance optimization for deleting elements from a vector: linear runtime at most!
- template <class T>
- void removeRowsFromVector(const std::set<unsigned int>& rowsToRemove, std::vector<T>& grid)
- {
- if (rowsToRemove.empty())
- return;
+template <class T>
+void removeRowsFromVector(const std::set<unsigned int>& rowsToRemove, std::vector<T>& grid)
+{
+ if (rowsToRemove.empty())
+ return;
- std::set<unsigned int>::const_iterator rowToSkipIndex = rowsToRemove.begin();
- unsigned int rowToSkip = *rowToSkipIndex;
+ std::set<unsigned int>::const_iterator rowToSkipIndex = rowsToRemove.begin();
+ unsigned int rowToSkip = *rowToSkipIndex;
- if (rowToSkip >= grid.size())
- return;
+ if (rowToSkip >= grid.size())
+ return;
- typename std::vector<T>::iterator insertPos = grid.begin() + rowToSkip;
+ typename std::vector<T>::iterator insertPos = grid.begin() + rowToSkip;
- for (unsigned int i = rowToSkip; i < grid.size(); ++i)
+ for (unsigned int i = rowToSkip; i < grid.size(); ++i)
+ {
+ if (i != rowToSkip)
{
- if (i != rowToSkip)
- {
- *insertPos = grid[i];
- ++insertPos;
- }
- else
- {
- ++rowToSkipIndex;
- if (rowToSkipIndex != rowsToRemove.end())
- rowToSkip = *rowToSkipIndex;
- }
+ *insertPos = grid[i];
+ ++insertPos;
}
- grid.erase(insertPos, grid.end());
- }
-
- //bubble sort using swap() instead of assignment: useful if assignment is very expensive
- template <class VectorData, typename CompareFct>
- void bubbleSwapSort(VectorData& folderCmp, CompareFct compare)
- {
- for (int i = folderCmp.size() - 2; i >= 0; --i)
+ else
{
- bool swapped = false;
- for (int j = 0; j <= i; ++j)
- if (compare(folderCmp[j + 1], folderCmp[j]))
- {
- folderCmp[j + 1].swap(folderCmp[j]);
- swapped = true;
- }
-
- if (!swapped)
- return;
+ ++rowToSkipIndex;
+ if (rowToSkipIndex != rowsToRemove.end())
+ rowToSkip = *rowToSkipIndex;
}
}
+ grid.erase(insertPos, grid.end());
+}
- //enhanced binary search template: returns an iterator
- template <class ForwardIterator, class T>
- inline
- ForwardIterator custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value)
+//bubble sort using swap() instead of assignment: useful if assignment is very expensive
+template <class VectorData, typename CompareFct>
+void bubbleSwapSort(VectorData& folderCmp, CompareFct compare)
+{
+ for (int i = folderCmp.size() - 2; i >= 0; --i)
{
- first = lower_bound(first, last, value);
- if (first != last && !(value < *first))
- return first;
- else
- return last;
- }
+ bool swapped = false;
+ for (int j = 0; j <= i; ++j)
+ if (compare(folderCmp[j + 1], folderCmp[j]))
+ {
+ folderCmp[j + 1].swap(folderCmp[j]);
+ swapped = true;
+ }
- //enhanced binary search template: returns an iterator
- template <class ForwardIterator, class T, typename Compare>
- inline
- ForwardIterator custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp)
- {
- first = lower_bound(first, last, value, comp);
- if (first != last && !comp(value, *first))
- return first;
- else
- return last;
+ if (!swapped)
+ return;
}
}
+//enhanced binary search template: returns an iterator
+template <class ForwardIterator, class T>
+inline
+ForwardIterator custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value)
+{
+ first = lower_bound(first, last, value);
+ if (first != last && !(value < *first))
+ return first;
+ else
+ return last;
+}
+
+//enhanced binary search template: returns an iterator
+template <class ForwardIterator, class T, typename Compare>
+inline
+ForwardIterator custom_binary_search(ForwardIterator first, ForwardIterator last, const T& value, Compare comp)
+{
+ first = lower_bound(first, last, value, comp);
+ if (first != last && !comp(value, *first))
+ return first;
+ else
+ return last;
+}
+}
+
//############################################################################
class Performance
@@ -185,4 +189,96 @@ wxString getCodeLocation(const wxString file, const int line);
//speed alternative: wxLogDebug(wxT("text")) + DebugView
+
+
+
+
+
+
+
+
+
+
+
+
+
+//---------------Inline Implementation---------------------------------------------------
+template <class T>
+inline
+T globalFunctions::readNumber(std::ifstream& stream)
+{
+ T result = 0;
+ stream.read(reinterpret_cast<char*>(&result), sizeof(T));
+ return result;
+}
+
+
+template <class T>
+inline
+void globalFunctions::writeNumber(std::ofstream& stream, T number)
+{
+ stream.write(reinterpret_cast<const char*>(&number), sizeof(T));
+}
+
+
+template <class T>
+inline
+T globalFunctions::readNumber(wxInputStream& stream)
+{
+ T result = 0;
+ stream.Read(&result, sizeof(T));
+ return result;
+}
+
+
+template <class T>
+inline
+void globalFunctions::writeNumber(wxOutputStream& stream, T number)
+{
+ stream.Write(&number, sizeof(T));
+}
+
+
+inline
+wxString globalFunctions::numberToWxString(const unsigned int number)
+{
+ return wxString::Format(wxT("%u"), number);
+}
+
+
+inline
+wxString globalFunctions::numberToWxString(const int number)
+{
+ return wxString::Format(wxT("%i"), number);
+}
+
+
+inline
+wxString globalFunctions::numberToWxString(const float number)
+{
+ return wxString::Format(wxT("%f"), number);
+}
+
+
+inline
+int globalFunctions::stringToInt(const std::string& number)
+{
+ return atoi(number.c_str());
+}
+
+
+inline
+long globalFunctions::stringToLong(const std::string& number)
+{
+ return atol(number.c_str());
+}
+
+
+inline
+double globalFunctions::stringToDouble(const std::string& number)
+{
+ return atof(number.c_str());
+}
+
+
#endif // GLOBALFUNCTIONS_H_INCLUDED
diff --git a/shared/localization.cpp b/shared/localization.cpp
index 20bf6d2e..ff14c980 100644
--- a/shared/localization.cpp
+++ b/shared/localization.cpp
@@ -1,6 +1,7 @@
#include "localization.h"
#include <wx/msgdlg.h>
#include "../shared/standardPaths.h"
+#include "../shared/stringConv.h"
#include "systemConstants.h"
#include <fstream>
#include <map>
@@ -112,6 +113,13 @@ LocalizationInfo::LocalizationInfo()
newEntry.languageFlag = wxT("brazil.png");
locMapping.push_back(newEntry);
+ newEntry.languageID = wxLANGUAGE_ROMANIAN;
+ newEntry.languageName = wxT("Română");
+ newEntry.languageFile = wxT("romanian.lng");
+ newEntry.translatorName = wxT("Alexandru Bogdan Munteanu");
+ newEntry.languageFlag = wxT("romania.png");
+ locMapping.push_back(newEntry);
+
newEntry.languageID = wxLANGUAGE_SLOVENIAN;
newEntry.languageName = wxT("SlovenÅ¡Äina");
newEntry.languageFile = wxT("slovenian.lng");
@@ -119,6 +127,13 @@ LocalizationInfo::LocalizationInfo()
newEntry.languageFlag = wxT("slovakia.png");
locMapping.push_back(newEntry);
+ newEntry.languageID = wxLANGUAGE_TURKISH;
+ newEntry.languageName = wxT("Türkçe");
+ newEntry.languageFile = wxT("turkish.lng");
+ newEntry.translatorName = wxT("H.Barbaros BIÇAKCI");
+ newEntry.languageFlag = wxT("turkey.png");
+ locMapping.push_back(newEntry);
+
newEntry.languageID = wxLANGUAGE_JAPANESE;
newEntry.languageName = wxT("日本語");
newEntry.languageFile = wxT("japanese.lng");
@@ -236,9 +251,9 @@ CustomLocale& CustomLocale::getInstance()
CustomLocale::CustomLocale() :
- wxLocale(wxLANGUAGE_DEFAULT), //setting a different language needn't be supported on all systems!
- translationDB(new Translation),
- currentLanguage(wxLANGUAGE_ENGLISH) {}
+ wxLocale(wxLANGUAGE_DEFAULT), //setting a different language needn't be supported on all systems!
+ translationDB(new Translation),
+ currentLanguage(wxLANGUAGE_ENGLISH) {}
inline
@@ -290,7 +305,7 @@ class UnicodeFileReader
{
public:
UnicodeFileReader(const wxString& filename) :
- inputFile(NULL)
+ inputFile(NULL)
{
//workaround to get a FILE* from a unicode filename
wxFFile dummyFile(filename, wxT("rb"));
@@ -363,8 +378,8 @@ void CustomLocale::setLanguage(const int language)
translationDB->clear();
if (!languageFile.empty())
{
- UnicodeFileReader langFile(FreeFileSync::getInstallationDir() + globalFunctions::FILE_NAME_SEPARATOR +
- wxT("Languages") + globalFunctions::FILE_NAME_SEPARATOR + languageFile);
+ UnicodeFileReader langFile(FreeFileSync::getInstallationDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) +
+ wxT("Languages") + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + languageFile);
if (langFile.isOkay())
{
int rowNumber = 0;
diff --git a/shared/localization.h b/shared/localization.h
index 2a5ee80d..0a5ca4fb 100644
--- a/shared/localization.h
+++ b/shared/localization.h
@@ -10,53 +10,55 @@ class Translation;
namespace FreeFileSync
{
- //language dependent global variables: need to be initialized by CustomLocale on program startup and language switch
+//language dependent global variables: need to be initialized by CustomLocale on program startup and language switch
- extern const wxChar* THOUSANDS_SEPARATOR;
- extern const wxChar* DECIMAL_POINT;
+extern const wxChar* THOUSANDS_SEPARATOR;
+extern const wxChar* DECIMAL_POINT;
- struct LocInfoLine
- {
- int languageID;
- wxString languageName;
- wxString languageFile;
- wxString translatorName;
- wxString languageFlag;
- };
-
- class LocalizationInfo
- {
- public:
- static const std::vector<LocInfoLine>& getMapping();
+struct LocInfoLine
+{
+ int languageID;
+ wxString languageName;
+ wxString languageFile;
+ wxString translatorName;
+ wxString languageFlag;
+};
+
+class LocalizationInfo
+{
+public:
+ static const std::vector<LocInfoLine>& getMapping();
- private:
- LocalizationInfo();
+private:
+ LocalizationInfo();
+ LocalizationInfo(const LocalizationInfo&);
+ LocalizationInfo& operator=(const LocalizationInfo&);
- std::vector<LocInfoLine> locMapping;
- };
+ std::vector<LocInfoLine> locMapping;
+};
- class CustomLocale : public wxLocale
- {
- public:
- static CustomLocale& getInstance();
+class CustomLocale : public wxLocale
+{
+public:
+ static CustomLocale& getInstance();
- void setLanguage(const int language);
+ void setLanguage(const int language);
- int getLanguage() const
- {
- return currentLanguage;
- }
+ int getLanguage() const
+ {
+ return currentLanguage;
+ }
- virtual const wxChar* GetString(const wxChar* szOrigString, const wxChar* szDomain = NULL) const;
+ virtual const wxChar* GetString(const wxChar* szOrigString, const wxChar* szDomain = NULL) const;
- private:
- CustomLocale();
+private:
+ CustomLocale();
- std::auto_ptr<Translation> translationDB;
- int currentLanguage;
- };
+ std::auto_ptr<Translation> translationDB;
+ int currentLanguage;
+};
}
#endif // MISC_H_INCLUDED
diff --git a/shared/loki/AbstractFactory.h b/shared/loki/AbstractFactory.h
new file mode 100644
index 00000000..8ff518dc
--- /dev/null
+++ b/shared/loki/AbstractFactory.h
@@ -0,0 +1,185 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_ABSTRACTFACTORY_INC_
+#define LOKI_ABSTRACTFACTORY_INC_
+
+// $Id: AbstractFactory.h 771 2006-10-27 18:05:03Z clitte_bbt $
+
+
+#include "Typelist.h"
+#include "Sequence.h"
+#include "TypeManip.h"
+#include "HierarchyGenerators.h"
+
+#include <cassert>
+
+/**
+ * \defgroup FactoriesGroup Factories
+ * \defgroup AbstractFactoryGroup Abstract Factory
+ * \ingroup FactoriesGroup
+ * \brief Implements an abstract object factory.
+ */
+
+/**
+ * \class AbstractFactory
+ * \ingroup AbstractFactoryGroup
+ * \brief Implements an abstract object factory.
+ */
+
+namespace Loki
+{
+
+////////////////////////////////////////////////////////////////////////////////
+// class template AbstractFactoryUnit
+// The building block of an Abstract Factory
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class AbstractFactoryUnit
+ {
+ public:
+ virtual T* DoCreate(Type2Type<T>) = 0;
+ virtual ~AbstractFactoryUnit() {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template AbstractFactory
+// Defines an Abstract Factory interface starting from a typelist
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ class TList,
+ template <class> class Unit = AbstractFactoryUnit
+ >
+ class AbstractFactory : public GenScatterHierarchy<TList, Unit>
+ {
+ public:
+ typedef TList ProductList;
+
+ template <class T> T* Create()
+ {
+ Unit<T>& unit = *this;
+ return unit.DoCreate(Type2Type<T>());
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template OpNewFactoryUnit
+// Creates an object by invoking the new operator
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class ConcreteProduct, class Base>
+ class OpNewFactoryUnit : public Base
+ {
+ typedef typename Base::ProductList BaseProductList;
+
+ protected:
+ typedef typename BaseProductList::Tail ProductList;
+
+ public:
+ typedef typename BaseProductList::Head AbstractProduct;
+ ConcreteProduct* DoCreate(Type2Type<AbstractProduct>)
+ {
+ return new ConcreteProduct;
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template PrototypeFactoryUnit
+// Creates an object by cloning a prototype
+// There is a difference between the implementation herein and the one described
+// in the book: GetPrototype and SetPrototype use the helper friend
+// functions DoGetPrototype and DoSetPrototype. The friend functions avoid
+// name hiding issues. Plus, GetPrototype takes a reference to pointer
+// instead of returning the pointer by value.
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class ConcreteProduct, class Base>
+ class PrototypeFactoryUnit : public Base
+ {
+ typedef typename Base::ProductList BaseProductList;
+
+ protected:
+ typedef typename BaseProductList::Tail ProductList;
+
+ public:
+ typedef typename BaseProductList::Head AbstractProduct;
+
+ PrototypeFactoryUnit(AbstractProduct* p = 0)
+ : pPrototype_(p)
+ {}
+
+ template <class CP, class Base1>
+ friend void DoGetPrototype(const PrototypeFactoryUnit<CP, Base1>& me,
+ typename Base1::ProductList::Head*& pPrototype);
+
+ template <class CP, class Base1>
+ friend void DoSetPrototype(PrototypeFactoryUnit<CP, Base1>& me,
+ typename Base1::ProductList::Head* pObj);
+
+ template <class U>
+ void GetPrototype(U*& p)
+ { return DoGetPrototype(*this, p); }
+
+ template <class U>
+ void SetPrototype(U* pObj)
+ { DoSetPrototype(*this, pObj); }
+
+ AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
+ {
+ assert(pPrototype_);
+ return pPrototype_->Clone();
+ }
+
+ private:
+ AbstractProduct* pPrototype_;
+ };
+
+ template <class CP, class Base>
+ inline void DoGetPrototype(const PrototypeFactoryUnit<CP, Base>& me,
+ typename Base::ProductList::Head*& pPrototype)
+ { pPrototype = me.pPrototype_; }
+
+ template <class CP, class Base>
+ inline void DoSetPrototype(PrototypeFactoryUnit<CP, Base>& me,
+ typename Base::ProductList::Head* pObj)
+ { me.pPrototype_ = pObj; }
+
+////////////////////////////////////////////////////////////////////////////////
+// class template ConcreteFactory
+// Implements an AbstractFactory interface
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ class AbstractFact,
+ template <class, class> class Creator = OpNewFactoryUnit,
+ class TList = typename AbstractFact::ProductList
+ >
+ class ConcreteFactory
+ : public GenLinearHierarchy<
+ typename TL::Reverse<TList>::Result, Creator, AbstractFact>
+ {
+ public:
+ typedef typename AbstractFact::ProductList ProductList;
+ typedef TList ConcreteProductList;
+ };
+
+} // namespace Loki
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/Allocator.h b/shared/loki/Allocator.h
new file mode 100644
index 00000000..a79ee061
--- /dev/null
+++ b/shared/loki/Allocator.h
@@ -0,0 +1,153 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2008 by Rich Sposato
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef LOKI_ALLOCATOR_HPP_INCLUDED
+#define LOKI_ALLOCATOR_HPP_INCLUDED
+
+// $Id: Allocator.h 896 2008-08-08 22:20:05Z syntheticpp $
+
+// Requires project to be compiled with loki/src/SmallObj.cpp and loki/src/Singleton.cpp
+
+#include <loki/SmallObj.h>
+
+
+namespace Loki
+{
+
+
+//-----------------------------------------------------------------------------
+
+/** @class LokiAllocator
+ Adapts Loki's Small-Object Allocator for STL container classes.
+ This class provides all the functionality required for STL allocators, but
+ uses Loki's Small-Object Allocator to perform actual memory operations.
+ Implementation comes from a post in Loki forums (by Rasmus Ekman?).
+ */
+template
+<
+ typename Type,
+ typename AllocT = Loki::AllocatorSingleton<>
+>
+class LokiAllocator
+{
+public:
+
+ typedef ::std::size_t size_type;
+ typedef ::std::ptrdiff_t difference_type;
+ typedef Type * pointer;
+ typedef const Type * const_pointer;
+ typedef Type & reference;
+ typedef const Type & const_reference;
+ typedef Type value_type;
+
+ /// Default constructor does nothing.
+ inline LokiAllocator( void ) throw() { }
+
+ /// Copy constructor does nothing.
+ inline LokiAllocator( const LokiAllocator & ) throw() { }
+
+ /// Type converting allocator constructor does nothing.
+ template < typename Type1 >
+ inline LokiAllocator( const LokiAllocator< Type1 > & ) throw() { }
+
+ /// Destructor does nothing.
+ inline ~LokiAllocator() throw() { }
+
+ /// Convert an allocator<Type> to an allocator <Type1>.
+ template < typename Type1 >
+ struct rebind
+ {
+ typedef LokiAllocator< Type1 > other;
+ };
+
+ /// Return address of reference to mutable element.
+ pointer address( reference elem ) const { return &elem; }
+
+ /// Return address of reference to const element.
+ const_pointer address( const_reference elem ) const { return &elem; }
+
+ /** Allocate an array of count elements. Warning! The true parameter in
+ the call to Allocate means this function can throw exceptions. This is
+ better than not throwing, and returning a null pointer in case the caller
+ assumes the return value is not null.
+ @param count # of elements in array.
+ @param hint Place where caller thinks allocation should occur.
+ @return Pointer to block of memory.
+ */
+ pointer allocate( size_type count, const void * hint = 0 )
+ {
+ (void)hint; // Ignore the hint.
+ void * p = AllocT::Instance().Allocate( count * sizeof( Type ), true );
+ return reinterpret_cast< pointer >( p );
+ }
+
+ /// Ask allocator to release memory at pointer with size bytes.
+ void deallocate( pointer p, size_type size )
+ {
+ AllocT::Instance().Deallocate( p, size * sizeof( Type ) );
+ }
+
+ /// Calculate max # of elements allocator can handle.
+ size_type max_size( void ) const throw()
+ {
+ // A good optimizer will see these calculations always produce the same
+ // value and optimize this function away completely.
+ const size_type max_bytes = size_type( -1 );
+ const size_type bytes = max_bytes / sizeof( Type );
+ return bytes;
+ }
+
+ /// Construct an element at the pointer.
+ void construct( pointer p, const Type & value )
+ {
+ // A call to global placement new forces a call to copy constructor.
+ ::new( p ) Type( value );
+ }
+
+ /// Destruct the object at pointer.
+ void destroy( pointer p )
+ {
+ // If the Type has no destructor, then some compilers complain about
+ // an unreferenced parameter, so use the void cast trick to prevent
+ // spurious warnings.
+ (void)p;
+ p->~Type();
+ }
+
+};
+
+//-----------------------------------------------------------------------------
+
+/** All equality operators return true since LokiAllocator is basically a
+ monostate design pattern, so all instances of it are identical.
+ */
+template < typename Type >
+inline bool operator == ( const LokiAllocator< Type > &, const LokiAllocator< Type > & )
+{
+ return true;
+}
+
+/** All inequality operators return false since LokiAllocator is basically a
+ monostate design pattern, so all instances of it are identical.
+ */
+template < typename Type >
+inline bool operator != ( const LokiAllocator< Type > & , const LokiAllocator< Type > & )
+{
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+
+} // namespace Loki
+
+#endif // LOKI_ALLOCATOR_INCLUDED
diff --git a/shared/loki/AssocVector.h b/shared/loki/AssocVector.h
new file mode 100644
index 00000000..905e0963
--- /dev/null
+++ b/shared/loki/AssocVector.h
@@ -0,0 +1,358 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_ASSOCVECTOR_INC_
+#define LOKI_ASSOCVECTOR_INC_
+
+// $Id: AssocVector.h 765 2006-10-18 13:55:32Z syntheticpp $
+
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+#include <utility>
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class template AssocVectorCompare
+// Used by AssocVector
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ template <class Value, class C>
+ class AssocVectorCompare : public C
+ {
+ typedef std::pair<typename C::first_argument_type, Value>
+ Data;
+ typedef typename C::first_argument_type first_argument_type;
+
+ public:
+ AssocVectorCompare()
+ {}
+
+ AssocVectorCompare(const C& src) : C(src)
+ {}
+
+ bool operator()(const first_argument_type& lhs,
+ const first_argument_type& rhs) const
+ { return C::operator()(lhs, rhs); }
+
+ bool operator()(const Data& lhs, const Data& rhs) const
+ { return operator()(lhs.first, rhs.first); }
+
+ bool operator()(const Data& lhs,
+ const first_argument_type& rhs) const
+ { return operator()(lhs.first, rhs); }
+
+ bool operator()(const first_argument_type& lhs,
+ const Data& rhs) const
+ { return operator()(lhs, rhs.first); }
+ };
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// class template AssocVector
+// An associative vector built as a syntactic drop-in replacement for std::map
+// BEWARE: AssocVector doesn't respect all map's guarantees, the most important
+// being:
+// * iterators are invalidated by insert and erase operations
+// * the complexity of insert/erase is O(N) not O(log N)
+// * value_type is std::pair<K, V> not std::pair<const K, V>
+// * iterators are random
+////////////////////////////////////////////////////////////////////////////////
+
+
+ template
+ <
+ class K,
+ class V,
+ class C = std::less<K>,
+ class A = std::allocator< std::pair<K, V> >
+ >
+ class AssocVector
+ : private std::vector< std::pair<K, V>, A >
+ , private Private::AssocVectorCompare<V, C>
+ {
+ typedef std::vector<std::pair<K, V>, A> Base;
+ typedef Private::AssocVectorCompare<V, C> MyCompare;
+
+ public:
+ typedef K key_type;
+ typedef V mapped_type;
+ typedef typename Base::value_type value_type;
+
+ typedef C key_compare;
+ typedef A allocator_type;
+ typedef typename A::reference reference;
+ typedef typename A::const_reference const_reference;
+ typedef typename Base::iterator iterator;
+ typedef typename Base::const_iterator const_iterator;
+ typedef typename Base::size_type size_type;
+ typedef typename Base::difference_type difference_type;
+ typedef typename A::pointer pointer;
+ typedef typename A::const_pointer const_pointer;
+ typedef typename Base::reverse_iterator reverse_iterator;
+ typedef typename Base::const_reverse_iterator const_reverse_iterator;
+
+ class value_compare
+ : public std::binary_function<value_type, value_type, bool>
+ , private key_compare
+ {
+ friend class AssocVector;
+
+ protected:
+ value_compare(key_compare pred) : key_compare(pred)
+ {}
+
+ public:
+ bool operator()(const value_type& lhs, const value_type& rhs) const
+ { return key_compare::operator()(lhs.first, rhs.first); }
+ };
+
+ // 23.3.1.1 construct/copy/destroy
+
+ explicit AssocVector(const key_compare& comp = key_compare(),
+ const A& alloc = A())
+ : Base(alloc), MyCompare(comp)
+ {}
+
+ template <class InputIterator>
+ AssocVector(InputIterator first, InputIterator last,
+ const key_compare& comp = key_compare(),
+ const A& alloc = A())
+ : Base(first, last, alloc), MyCompare(comp)
+ {
+ MyCompare& me = *this;
+ std::sort(begin(), end(), me);
+ }
+
+ AssocVector& operator=(const AssocVector& rhs)
+ {
+ AssocVector(rhs).swap(*this);
+ return *this;
+ }
+
+ // iterators:
+ // The following are here because MWCW gets 'using' wrong
+ iterator begin() { return Base::begin(); }
+ const_iterator begin() const { return Base::begin(); }
+ iterator end() { return Base::end(); }
+ const_iterator end() const { return Base::end(); }
+ reverse_iterator rbegin() { return Base::rbegin(); }
+ const_reverse_iterator rbegin() const { return Base::rbegin(); }
+ reverse_iterator rend() { return Base::rend(); }
+ const_reverse_iterator rend() const { return Base::rend(); }
+
+ // capacity:
+ bool empty() const { return Base::empty(); }
+ size_type size() const { return Base::size(); }
+ size_type max_size() { return Base::max_size(); }
+
+ // 23.3.1.2 element access:
+ mapped_type& operator[](const key_type& key)
+ { return insert(value_type(key, mapped_type())).first->second; }
+
+ // modifiers:
+ std::pair<iterator, bool> insert(const value_type& val)
+ {
+ bool found(true);
+ iterator i(lower_bound(val.first));
+
+ if (i == end() || this->operator()(val.first, i->first))
+ {
+ i = Base::insert(i, val);
+ found = false;
+ }
+ return std::make_pair(i, !found);
+ }
+ //Section [23.1.2], Table 69
+ //http://developer.apple.com/documentation/DeveloperTools/gcc-3.3/libstdc++/23_containers/howto.html#4
+ iterator insert(iterator pos, const value_type& val)
+ {
+ if( (pos == begin() || this->operator()(*(pos-1),val)) &&
+ (pos == end() || this->operator()(val, *pos)) )
+ {
+ return Base::insert(pos, val);
+ }
+ return insert(val).first;
+ }
+
+ template <class InputIterator>
+ void insert(InputIterator first, InputIterator last)
+ { for (; first != last; ++first) insert(*first); }
+
+ void erase(iterator pos)
+ { Base::erase(pos); }
+
+ size_type erase(const key_type& k)
+ {
+ iterator i(find(k));
+ if (i == end()) return 0;
+ erase(i);
+ return 1;
+ }
+
+ void erase(iterator first, iterator last)
+ { Base::erase(first, last); }
+
+ void swap(AssocVector& other)
+ {
+ Base::swap(other);
+ MyCompare& me = *this;
+ MyCompare& rhs = other;
+ std::swap(me, rhs);
+ }
+
+ void clear()
+ { Base::clear(); }
+
+ // observers:
+ key_compare key_comp() const
+ { return *this; }
+
+ value_compare value_comp() const
+ {
+ const key_compare& comp = *this;
+ return value_compare(comp);
+ }
+
+ // 23.3.1.3 map operations:
+ iterator find(const key_type& k)
+ {
+ iterator i(lower_bound(k));
+ if (i != end() && this->operator()(k, i->first))
+ {
+ i = end();
+ }
+ return i;
+ }
+
+ const_iterator find(const key_type& k) const
+ {
+ const_iterator i(lower_bound(k));
+ if (i != end() && this->operator()(k, i->first))
+ {
+ i = end();
+ }
+ return i;
+ }
+
+ size_type count(const key_type& k) const
+ { return find(k) != end(); }
+
+ iterator lower_bound(const key_type& k)
+ {
+ MyCompare& me = *this;
+ return std::lower_bound(begin(), end(), k, me);
+ }
+
+ const_iterator lower_bound(const key_type& k) const
+ {
+ const MyCompare& me = *this;
+ return std::lower_bound(begin(), end(), k, me);
+ }
+
+ iterator upper_bound(const key_type& k)
+ {
+ MyCompare& me = *this;
+ return std::upper_bound(begin(), end(), k, me);
+ }
+
+ const_iterator upper_bound(const key_type& k) const
+ {
+ const MyCompare& me = *this;
+ return std::upper_bound(begin(), end(), k, me);
+ }
+
+ std::pair<iterator, iterator> equal_range(const key_type& k)
+ {
+ MyCompare& me = *this;
+ return std::equal_range(begin(), end(), k, me);
+ }
+
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type& k) const
+ {
+ const MyCompare& me = *this;
+ return std::equal_range(begin(), end(), k, me);
+ }
+
+ template <class K1, class V1, class C1, class A1>
+ friend bool operator==(const AssocVector<K1, V1, C1, A1>& lhs,
+ const AssocVector<K1, V1, C1, A1>& rhs);
+
+ bool operator<(const AssocVector& rhs) const
+ {
+ const Base& me = *this;
+ const Base& yo = rhs;
+ return me < yo;
+ }
+
+ template <class K1, class V1, class C1, class A1>
+ friend bool operator!=(const AssocVector<K1, V1, C1, A1>& lhs,
+ const AssocVector<K1, V1, C1, A1>& rhs);
+
+ template <class K1, class V1, class C1, class A1>
+ friend bool operator>(const AssocVector<K1, V1, C1, A1>& lhs,
+ const AssocVector<K1, V1, C1, A1>& rhs);
+
+ template <class K1, class V1, class C1, class A1>
+ friend bool operator>=(const AssocVector<K1, V1, C1, A1>& lhs,
+ const AssocVector<K1, V1, C1, A1>& rhs);
+
+ template <class K1, class V1, class C1, class A1>
+ friend bool operator<=(const AssocVector<K1, V1, C1, A1>& lhs,
+ const AssocVector<K1, V1, C1, A1>& rhs);
+ };
+
+ template <class K, class V, class C, class A>
+ inline bool operator==(const AssocVector<K, V, C, A>& lhs,
+ const AssocVector<K, V, C, A>& rhs)
+ {
+ const std::vector<std::pair<K, V>, A>& me = lhs;
+ return me == rhs;
+ }
+
+ template <class K, class V, class C, class A>
+ inline bool operator!=(const AssocVector<K, V, C, A>& lhs,
+ const AssocVector<K, V, C, A>& rhs)
+ { return !(lhs == rhs); }
+
+ template <class K, class V, class C, class A>
+ inline bool operator>(const AssocVector<K, V, C, A>& lhs,
+ const AssocVector<K, V, C, A>& rhs)
+ { return rhs < lhs; }
+
+ template <class K, class V, class C, class A>
+ inline bool operator>=(const AssocVector<K, V, C, A>& lhs,
+ const AssocVector<K, V, C, A>& rhs)
+ { return !(lhs < rhs); }
+
+ template <class K, class V, class C, class A>
+ inline bool operator<=(const AssocVector<K, V, C, A>& lhs,
+ const AssocVector<K, V, C, A>& rhs)
+ { return !(rhs < lhs); }
+
+
+ // specialized algorithms:
+ template <class K, class V, class C, class A>
+ void swap(AssocVector<K, V, C, A>& lhs, AssocVector<K, V, C, A>& rhs)
+ { lhs.swap(rhs); }
+
+} // namespace Loki
+
+#endif // end file guardian
+
diff --git a/shared/loki/CachedFactory.h b/shared/loki/CachedFactory.h
new file mode 100644
index 00000000..15c9a801
--- /dev/null
+++ b/shared/loki/CachedFactory.h
@@ -0,0 +1,1167 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 by Guillaume Chatelet
+//
+// Code covered by the MIT License
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+//
+// The authors make no representations about the suitability of this software
+// for any purpose. It is provided "as is" without express or implied warranty.
+//
+// This code DOES NOT accompany the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+//
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_CACHEDFACTORY_INC_
+#define LOKI_CACHEDFACTORY_INC_
+
+// $Id: CachedFactory.h 950 2009-01-26 19:45:54Z syntheticpp $
+
+#include <functional>
+#include <algorithm>
+#include <iostream>
+#include <vector>
+#include <iterator>
+#include <map>
+#include <cassert>
+#include <loki/Key.h>
+
+#ifdef DO_EXTRA_LOKI_TESTS
+ #define D( x ) x
+#else
+ #define D( x ) ;
+#endif
+
+#if defined(_MSC_VER) || defined(__CYGWIN__)
+#include <time.h>
+#endif
+
+/**
+ * \defgroup FactoriesGroup Factories
+ * \defgroup CachedFactoryGroup Cached Factory
+ * \ingroup FactoriesGroup
+ * \brief CachedFactory provides an extension of a Factory with caching
+ * support.
+ *
+ * Once used objects are returned to the CachedFactory that manages its
+ * destruction.
+ * If your code uses lots of "long to construct/destruct objects" using the
+ * CachedFactory will surely speedup the execution.
+ */
+namespace Loki
+{
+/**
+ * \defgroup EncapsulationPolicyCachedFactoryGroup Encapsulation policies
+ * \ingroup CachedFactoryGroup
+ * \brief Defines how the object is returned to the client
+ */
+ /**
+ * \class SimplePointer
+ * \ingroup EncapsulationPolicyCachedFactoryGroup
+ * \brief No encaspulation : returns the pointer
+ *
+ * This implementation does not make any encapsulation.
+ * It simply returns the object's pointer.
+ */
+ template<class AbstractProduct>
+ class SimplePointer
+ {
+ protected:
+ typedef AbstractProduct* ProductReturn;
+ ProductReturn encapsulate(AbstractProduct* pProduct)
+ {
+ return pProduct;
+ }
+
+ AbstractProduct* release(ProductReturn &pProduct)
+ {
+ AbstractProduct* pPointer(pProduct);
+ pProduct=NULL;
+ return pPointer;
+ }
+ const char* name(){return "pointer";}
+ };
+
+/**
+ * \defgroup CreationPolicyCachedFactoryGroup Creation policies
+ * \ingroup CachedFactoryGroup
+ * \brief Defines a way to limit the creation operation.
+ *
+ * For instance one may want to be alerted (Exception) when
+ * - Cache has created a more than X object within the last x seconds
+ * - Cache creation rate has increased dramatically
+ * .
+ * which may result from bad caching strategy, or critical overload
+ */
+ /**
+ * \class NeverCreate
+ * \ingroup CreationPolicyCachedFactoryGroup
+ * \brief Never allows creation. Testing purposes only.
+ *
+ * Using this policy will throw an exception.
+ */
+ class NeverCreate
+ {
+ protected:
+ struct Exception : public std::exception
+ {
+ const char* what() const throw() { return "NeverFetch Policy : No Fetching allowed"; }
+ };
+
+ bool canCreate()
+ {
+ throw Exception();
+ }
+
+ void onCreate(){}
+ void onDestroy(){}
+ const char* name(){return "never";}
+ };
+
+ /**
+ * \class AlwaysCreate
+ * \ingroup CreationPolicyCachedFactoryGroup
+ * \brief Always allows creation.
+ *
+ * Doesn't limit the creation in any way
+ */
+ class AlwaysCreate
+ {
+ protected:
+ bool canCreate()
+ {
+ return true;
+ }
+
+ void onCreate(){}
+ void onDestroy(){}
+ const char* name(){return "always";}
+ };
+
+
+ /**
+ * \class RateLimitedCreation
+ * \ingroup CreationPolicyCachedFactoryGroup
+ * \brief Limit in rate.
+ *
+ * This implementation will prevent from Creating more than maxCreation objects
+ * within byTime ms by throwing an exception.
+ * Could be usefull to detect prevent loads (http connection for instance).
+ * Use the setRate method to set the rate parameters.
+ * default is 10 objects in a second.
+ */
+ // !! CAUTION !!
+ // The std::clock() function is not quite precise
+ // under linux this policy might not work.
+ // TODO : get a better implementation (platform dependant)
+ class RateLimitedCreation
+ {
+ private:
+ typedef std::vector< clock_t > Vector;
+ Vector m_vTimes;
+ unsigned maxCreation;
+ clock_t timeValidity;
+ clock_t lastUpdate;
+
+ void cleanVector()
+ {
+ using namespace std;
+ clock_t currentTime = clock();
+ D( cout << "currentTime = " << currentTime<< endl; )
+ D( cout << "currentTime - lastUpdate = " << currentTime - lastUpdate<< endl; )
+ if(currentTime - lastUpdate > timeValidity)
+ {
+ m_vTimes.clear();
+ D( cout << " is less than time validity " << timeValidity; )
+ D( cout << " so clearing vector" << endl; )
+ }
+ else
+ {
+ D( cout << "Cleaning time less than " << currentTime - timeValidity << endl; )
+ D( displayVector(); )
+ Vector::iterator newEnd = remove_if(m_vTimes.begin(), m_vTimes.end(), bind2nd(less<clock_t>(), currentTime - timeValidity));
+ // this rearrangement might be costly, consider optimization
+ // by calling cleanVector in less used onCreate function
+ // ... although it may not be correct
+ m_vTimes.erase(newEnd, m_vTimes.end());
+ D( displayVector(); )
+ }
+ lastUpdate = currentTime;
+ }
+#ifdef DO_EXTRA_LOKI_TESTS
+ void displayVector()
+ {
+ std::cout << "Vector : ";
+ copy(m_vTimes.begin(), m_vTimes.end(), std::ostream_iterator<clock_t>(std::cout, " "));
+ std::cout << std::endl;
+ }
+#endif
+ protected:
+ RateLimitedCreation() : maxCreation(10), timeValidity(CLOCKS_PER_SEC), lastUpdate(clock())
+ {}
+
+ struct Exception : public std::exception
+ {
+ const char* what() const throw() { return "RateLimitedCreation Policy : Exceeded the authorized creation rate"; }
+ };
+
+ bool canCreate()
+ {
+ cleanVector();
+ if(m_vTimes.size()>maxCreation)
+ throw Exception();
+ else
+ return true;
+ }
+
+ void onCreate()
+ {
+ m_vTimes.push_back(clock());
+ }
+
+ void onDestroy()
+ {
+ }
+ const char* name(){return "rate limited";}
+ public:
+ // set the creation rate
+ // No more than maxCreation within byTime milliseconds
+ void setRate(unsigned maxCreation, unsigned byTime)
+ {
+ assert(byTime>0);
+ this->maxCreation = maxCreation;
+ this->timeValidity = static_cast<clock_t>(byTime * CLOCKS_PER_SEC / 1000);
+ D( std::cout << "Setting no more than "<< maxCreation <<" creation within " << this->timeValidity <<" ms"<< std::endl; )
+ }
+ };
+
+ /**
+ * \class AmountLimitedCreation
+ * \ingroup CreationPolicyCachedFactoryGroup
+ * \brief Limit by number of objects
+ *
+ * This implementation will prevent from Creating more than maxCreation objects
+ * within byTime ms by calling eviction policy.
+ * Use the setRate method to set the rate parameters.
+ * default is 10 objects.
+ */
+ class AmountLimitedCreation
+ {
+ private:
+ unsigned maxCreation;
+ unsigned created;
+
+ protected:
+ AmountLimitedCreation() : maxCreation(10), created(0)
+ {}
+
+ bool canCreate()
+ {
+ return !(created>=maxCreation);
+ }
+
+ void onCreate()
+ {
+ ++created;
+ }
+
+ void onDestroy()
+ {
+ --created;
+ }
+ const char* name(){return "amount limited";}
+ public:
+ // set the creation max amount
+ void setMaxCreation(unsigned maxCreation)
+ {
+ assert(maxCreation>0);
+ this->maxCreation = maxCreation;
+ D( std::cout << "Setting no more than " << maxCreation <<" creation" << std::endl; )
+ }
+ };
+
+/**
+ * \defgroup EvictionPolicyCachedFactoryGroup Eviction policies
+ * \ingroup CachedFactoryGroup
+ * \brief Gathers informations about the stored objects and choose a
+ * candidate for eviction.
+ */
+
+ class EvictionException : public std::exception
+ {
+ public:
+ const char* what() const throw() { return "Eviction Policy : trying to make room but no objects are available"; }
+ };
+
+ // The following class is intented to provide helpers to sort
+ // the container that will hold an eviction score
+ template
+ <
+ typename ST, // Score type
+ typename DT // Data type
+ >
+ class EvictionHelper
+ {
+ protected:
+ typedef typename std::map< DT, ST > HitMap;
+ typedef typename HitMap::iterator HitMapItr;
+ private:
+ typedef std::pair< ST, DT > SwappedPair;
+ typedef std::multimap< ST, DT > SwappedHitMap;
+ typedef typename SwappedHitMap::iterator SwappedHitMapItr;
+ protected:
+ HitMap m_mHitCount;
+
+ // This function sorts the map according to the score
+ // and returns the lower bound of the sorted container
+ DT& getLowerBound(){
+ assert(!m_mHitCount.empty());
+ // inserting the swapped pair into a multimap
+ SwappedHitMap copyMap;
+ for(HitMapItr itr = m_mHitCount.begin(); itr != m_mHitCount.end(); ++itr)
+ copyMap.insert(SwappedPair((*itr).second, (*itr).first));
+ if((*copyMap.rbegin()).first == 0) // the higher score is 0 ...
+ throw EvictionException(); // there is no key evict
+ return (*copyMap.begin()).second;
+ }
+ };
+
+ /**
+ * \class EvictLRU
+ * \ingroup EvictionPolicyCachedFactoryGroup
+ * \brief Evicts least accessed objects first.
+ *
+ * Implementation of the Least recent used algorithm as
+ * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
+ *
+ * WARNING : If an object is heavily fetched
+ * (more than ULONG_MAX = UINT_MAX = 4294967295U)
+ * it could unfortunately be removed from the cache.
+ */
+ template
+ <
+ typename DT, // Data Type (AbstractProduct*)
+ typename ST = unsigned // default data type to use as Score Type
+ >
+ class EvictLRU : public EvictionHelper< ST , DT >
+ {
+ private:
+ typedef EvictionHelper< ST , DT > EH;
+ protected:
+
+ virtual ~EvictLRU(){}
+
+ // OnStore initialize the counter for the new key
+ // If the key already exists, the counter is reseted
+ void onCreate(const DT& key)
+ {
+ EH::m_mHitCount[key] = 0;
+ }
+
+ void onFetch(const DT&)
+ {
+ }
+
+ // onRelease increments the hit counter associated with the object
+ void onRelease(const DT& key)
+ {
+ ++(EH::m_mHitCount[key]);
+ }
+
+ void onDestroy(const DT& key)
+ {
+ EH::m_mHitCount.erase(key);
+ }
+
+ // this function is implemented in Cache and redirected
+ // to the Storage Policy
+ virtual void remove(DT const key)=0;
+
+ // LRU Eviction policy
+ void evict()
+ {
+ remove(EH::getLowerBound());
+ }
+ const char* name(){return "LRU";}
+ };
+
+ /**
+ * \class EvictAging
+ * \ingroup EvictionPolicyCachedFactoryGroup
+ * \brief LRU aware of the time span of use
+ *
+ * Implementation of the Aging algorithm as
+ * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
+ *
+ * This method is much more costly than evict LRU so
+ * if you need extreme performance consider switching to EvictLRU
+ */
+ template
+ <
+ typename DT, // Data Type (AbstractProduct*)
+ typename ST = unsigned // default data type to use as Score Type
+ >
+ class EvictAging : public EvictionHelper< ST, DT >
+ {
+ private:
+ EvictAging(const EvictAging&);
+ EvictAging& operator=(const EvictAging&);
+ typedef EvictionHelper< ST, DT > EH;
+ typedef typename EH::HitMap HitMap;
+ typedef typename EH::HitMapItr HitMapItr;
+
+ // update the counter
+ template<class T> struct updateCounter : public std::unary_function<T, void>
+ {
+ updateCounter(const DT& key): key_(key){}
+ void operator()(T x)
+ {
+ x.second = (x.first == key_ ? (x.second >> 1) | ( 1 << ((sizeof(ST)-1)*8) ) : x.second >> 1);
+ D( std::cout << x.second << std::endl; )
+ }
+ const DT &key_;
+ updateCounter(const updateCounter& rhs) : key_(rhs.key_){}
+ private:
+ updateCounter& operator=(const updateCounter& rhs);
+ };
+ protected:
+ EvictAging(){}
+ virtual ~EvictAging(){}
+
+ // OnStore initialize the counter for the new key
+ // If the key already exists, the counter is reseted
+ void onCreate(const DT& key){
+ EH::m_mHitCount[key] = 0;
+ }
+
+ void onFetch(const DT&){}
+
+ // onRelease increments the hit counter associated with the object
+ // Updating every counters by iterating over the map
+ // If the key is the key of the fetched object :
+ // the counter is shifted to the right and it's MSB is set to 1
+ // else
+ // the counter is shifted to the left
+ void onRelease(const DT& key)
+ {
+ std::for_each(EH::m_mHitCount.begin(), EH::m_mHitCount.end(), updateCounter< typename HitMap::value_type >(key));
+ }
+
+ void onDestroy(const DT& key)
+ {
+ EH::m_mHitCount.erase(key);
+ }
+
+ // this function is implemented in Cache and redirected
+ // to the Storage Policy
+ virtual void remove(DT const key)=0;
+
+ // LRU with Aging Eviction policy
+ void evict()
+ {
+ remove(EH::getLowerBound());
+ }
+ const char* name(){return "LRU with aging";}
+ };
+
+ /**
+ * \class EvictRandom
+ * \ingroup EvictionPolicyCachedFactoryGroup
+ * \brief Evicts a random object
+ *
+ * Implementation of the Random algorithm as
+ * described in http://en.wikipedia.org/wiki/Page_replacement_algorithms .
+ */
+ template
+ <
+ typename DT, // Data Type (AbstractProduct*)
+ typename ST = void // Score Type not used by this policy
+ >
+ class EvictRandom
+ {
+ private:
+ std::vector< DT > m_vKeys;
+ typedef typename std::vector< DT >::size_type size_type;
+ typedef typename std::vector< DT >::iterator iterator;
+
+ protected:
+
+ virtual ~EvictRandom(){}
+
+ void onCreate(const DT&){
+ }
+
+ void onFetch(const DT& ){
+ }
+
+ void onRelease(const DT& key){
+ m_vKeys.push_back(key);
+ }
+
+ void onDestroy(const DT& key){
+ using namespace std;
+ m_vKeys.erase(remove_if(m_vKeys.begin(), m_vKeys.end(), bind2nd(equal_to< DT >(), key)), m_vKeys.end());
+ }
+
+ // Implemented in Cache and redirected to the Storage Policy
+ virtual void remove(DT const key)=0;
+
+ // Random Eviction policy
+ void evict()
+ {
+ if(m_vKeys.empty())
+ throw EvictionException();
+ size_type random = static_cast<size_type>((m_vKeys.size()*rand())/(static_cast<size_type>(RAND_MAX) + 1));
+ remove(*(m_vKeys.begin()+random));
+ }
+ const char* name(){return "random";}
+ };
+
+/**
+ * \defgroup StatisticPolicyCachedFactoryGroup Statistic policies
+ * \ingroup CachedFactoryGroup
+ * \brief Gathers information about the cache.
+ *
+ * For debugging purpose this policy proposes to gather informations
+ * about the cache. This could be useful to determine whether the cache is
+ * mandatory or if the policies are well suited to the application.
+ */
+ /**
+ * \class NoStatisticPolicy
+ * \ingroup StatisticPolicyCachedFactoryGroup
+ * \brief Do nothing
+ *
+ * Should be used in release code for better performances
+ */
+ class NoStatisticPolicy
+ {
+ protected:
+ void onDebug(){}
+ void onFetch(){}
+ void onRelease(){}
+ void onCreate(){}
+ void onDestroy(){}
+ const char* name(){return "no";}
+ };
+
+ /**
+ * \class SimpleStatisticPolicy
+ * \ingroup StatisticPolicyCachedFactoryGroup
+ * \brief Simple statistics
+ *
+ * Provides the following informations about the cache :
+ * - Created objects
+ * - Fetched objects
+ * - Destroyed objects
+ * - Cache hit
+ * - Cache miss
+ * - Currently allocated
+ * - Currently out
+ * - Cache overall efficiency
+ */
+ class SimpleStatisticPolicy
+ {
+ private:
+ unsigned allocated, created, hit, out, fetched;
+ protected:
+ SimpleStatisticPolicy() : allocated(0), created(0), hit(0), out(0), fetched(0)
+ {
+ }
+
+ void onDebug()
+ {
+ using namespace std;
+ cout << "############################" << endl;
+ cout << "## About this cache " << this << endl;
+ cout << "## + Created objects : " << created << endl;
+ cout << "## + Fetched objects : " << fetched << endl;
+ cout << "## + Destroyed objects : " << created - allocated << endl;
+ cout << "## + Cache hit : " << hit << endl;
+ cout << "## + Cache miss : " << fetched - hit << endl;
+ cout << "## + Currently allocated : " << allocated << endl;
+ cout << "## + Currently out : " << out << endl;
+ cout << "############################" << endl;
+ if(fetched!=0){
+ cout << "## Overall efficiency " << 100*double(hit)/fetched <<"%"<< endl;
+ cout << "############################" << endl;
+ }
+ cout << endl;
+ }
+
+ void onFetch()
+ {
+ ++fetched;
+ ++out;
+ ++hit;
+ }
+ void onRelease()
+ {
+ --out;
+ }
+ void onCreate()
+ {
+ ++created;
+ ++allocated;
+ --hit;
+ }
+ void onDestroy()
+ {
+ --allocated;
+ }
+
+ const char* name(){return "simple";}
+ public:
+ unsigned getCreated(){return created;}
+ unsigned getFetched(){return fetched;}
+ unsigned getHit(){return hit;}
+ unsigned getMissed(){return fetched - hit;}
+ unsigned getAllocated(){return allocated;}
+ unsigned getOut(){return out;}
+ unsigned getDestroyed(){return created-allocated;}
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Cache Factory definition
+ ///////////////////////////////////////////////////////////////////////////
+ class CacheException : public std::exception
+ {
+ public:
+ const char* what() const throw() { return "Internal Cache Error"; }
+ };
+
+ /**
+ * \class CachedFactory
+ * \ingroup CachedFactoryGroup
+ * \brief Factory with caching support
+ *
+ * This class acts as a Factory (it creates objects)
+ * but also keeps the already created objects to prevent
+ * long constructions time.
+ *
+ * Note this implementation do not retain ownership.
+ */
+ template
+ <
+ class AbstractProduct,
+ typename IdentifierType,
+ typename CreatorParmTList = NullType,
+ template<class> class EncapsulationPolicy = SimplePointer,
+ class CreationPolicy = AlwaysCreate,
+ template <typename , typename> class EvictionPolicy = EvictRandom,
+ class StatisticPolicy = NoStatisticPolicy,
+ template<typename, class> class FactoryErrorPolicy = DefaultFactoryError,
+ class ObjVector = std::vector<AbstractProduct*>
+ >
+ class CachedFactory :
+ protected EncapsulationPolicy<AbstractProduct>,
+ public CreationPolicy, public StatisticPolicy, EvictionPolicy< AbstractProduct * , unsigned >
+ {
+ private:
+ typedef Factory< AbstractProduct, IdentifierType, CreatorParmTList, FactoryErrorPolicy> MyFactory;
+ typedef FactoryImpl< AbstractProduct, IdentifierType, CreatorParmTList > Impl;
+ typedef Functor< AbstractProduct* , CreatorParmTList > ProductCreator;
+ typedef EncapsulationPolicy<AbstractProduct> NP;
+ typedef CreationPolicy CP;
+ typedef StatisticPolicy SP;
+ typedef EvictionPolicy< AbstractProduct* , unsigned > EP;
+
+ typedef typename Impl::Parm1 Parm1;
+ typedef typename Impl::Parm2 Parm2;
+ typedef typename Impl::Parm3 Parm3;
+ typedef typename Impl::Parm4 Parm4;
+ typedef typename Impl::Parm5 Parm5;
+ typedef typename Impl::Parm6 Parm6;
+ typedef typename Impl::Parm7 Parm7;
+ typedef typename Impl::Parm8 Parm8;
+ typedef typename Impl::Parm9 Parm9;
+ typedef typename Impl::Parm10 Parm10;
+ typedef typename Impl::Parm11 Parm11;
+ typedef typename Impl::Parm12 Parm12;
+ typedef typename Impl::Parm13 Parm13;
+ typedef typename Impl::Parm14 Parm14;
+ typedef typename Impl::Parm15 Parm15;
+
+ public:
+ typedef typename NP::ProductReturn ProductReturn;
+ private:
+ typedef Key< Impl, IdentifierType > MyKey;
+ typedef std::map< MyKey, ObjVector > KeyToObjVectorMap;
+ typedef std::map< AbstractProduct*, MyKey > FetchedObjToKeyMap;
+
+ MyFactory factory;
+ KeyToObjVectorMap fromKeyToObjVector;
+ FetchedObjToKeyMap providedObjects;
+ unsigned outObjects;
+
+ ObjVector& getContainerFromKey(MyKey key){
+ return fromKeyToObjVector[key];
+ }
+
+ AbstractProduct* const getPointerToObjectInContainer(ObjVector &entry)
+ {
+ if(entry.empty()) // No object available
+ { // the object will be created in the calling function.
+ // It has to be created in the calling function because of
+ // the variable number of parameters for CreateObject(...) method
+ return NULL;
+ }
+ else
+ { // returning the found object
+ AbstractProduct* pObject(entry.back());
+ assert(pObject!=NULL);
+ entry.pop_back();
+ return pObject;
+ }
+ }
+
+ bool shouldCreateObject(AbstractProduct * const pProduct){
+ if(pProduct!=NULL) // object already exists
+ return false;
+ if(CP::canCreate()==false) // Are we allowed to Create ?
+ EP::evict(); // calling Eviction Policy to clean up
+ return true;
+ }
+
+ void ReleaseObjectFromContainer(ObjVector &entry, AbstractProduct * const object)
+ {
+ entry.push_back(object);
+ }
+
+ void onFetch(AbstractProduct * const pProduct)
+ {
+ SP::onFetch();
+ EP::onFetch(pProduct);
+ ++outObjects;
+ }
+
+ void onRelease(AbstractProduct * const pProduct)
+ {
+ SP::onRelease();
+ EP::onRelease(pProduct);
+ --outObjects;
+ }
+
+ void onCreate(AbstractProduct * const pProduct)
+ {
+ CP::onCreate();
+ SP::onCreate();
+ EP::onCreate(pProduct);
+ }
+
+ void onDestroy(AbstractProduct * const pProduct)
+ {
+ CP::onDestroy();
+ SP::onDestroy();
+ EP::onDestroy(pProduct);
+ }
+
+ // delete the object
+ template<class T> struct deleteObject : public std::unary_function<T, void>
+ {
+ void operator()(T x){ delete x; }
+ };
+
+ // delete the objects in the vector
+ template<class T> struct deleteVectorObjects : public std::unary_function<T, void>
+ {
+ void operator()(T x){
+ ObjVector &vec(x.second);
+ std::for_each(vec.begin(), vec.end(), deleteObject< typename ObjVector::value_type>());
+ }
+ };
+
+ // delete the keys of the map
+ template<class T> struct deleteMapKeys : public std::unary_function<T, void>
+ {
+ void operator()(T x){ delete x.first; }
+ };
+
+ protected:
+ virtual void remove(AbstractProduct * const pProduct)
+ {
+ typename FetchedObjToKeyMap::iterator fetchedItr = providedObjects.find(pProduct);
+ if(fetchedItr!=providedObjects.end()) // object is unreleased.
+ throw CacheException();
+ bool productRemoved = false;
+ typename KeyToObjVectorMap::iterator objVectorItr;
+ typename ObjVector::iterator objItr;
+ for(objVectorItr=fromKeyToObjVector.begin();objVectorItr!=fromKeyToObjVector.end();++objVectorItr)
+ {
+ ObjVector &v((*objVectorItr).second);
+ objItr = remove_if(v.begin(), v.end(), std::bind2nd(std::equal_to<AbstractProduct*>(), pProduct));
+ if(objItr != v.end()) // we found the vector containing pProduct and removed it
+ {
+ onDestroy(pProduct); // warning policies we are about to destroy an object
+ v.erase(objItr, v.end()); // real removing
+ productRemoved = true;
+ break;
+ }
+ }
+ if(productRemoved==false)
+ throw CacheException(); // the product is not in the cache ?!
+ delete pProduct; // deleting it
+ }
+
+ public:
+ CachedFactory() : factory(), fromKeyToObjVector(), providedObjects(), outObjects(0)
+ {
+ }
+
+ ~CachedFactory()
+ {
+ using namespace std;
+ // debug information
+ SP::onDebug();
+ // cleaning the Cache
+ for_each(fromKeyToObjVector.begin(), fromKeyToObjVector.end(),
+ deleteVectorObjects< typename KeyToObjVectorMap::value_type >()
+ );
+ if(!providedObjects.empty())
+ {
+ // The factory is responsible for the creation and destruction of objects.
+ // If objects are out during the destruction of the Factory : deleting anyway.
+ // This might not be a good idea. But throwing an exception in a destructor is
+ // considered as a bad pratice and asserting might be too much.
+ // What to do ? Leaking memory or corrupting in use pointers ? hmm...
+ D( cout << "====>> Cache destructor : deleting "<< providedObjects.size()<<" in use objects <<====" << endl << endl; )
+ for_each(providedObjects.begin(), providedObjects.end(),
+ deleteMapKeys< typename FetchedObjToKeyMap::value_type >()
+ );
+ }
+ }
+
+ ///////////////////////////////////
+ // Acts as the proxy pattern and //
+ // forwards factory methods //
+ ///////////////////////////////////
+
+ bool Register(const IdentifierType& id, ProductCreator creator)
+ {
+ return factory.Register(id, creator);
+ }
+
+ template <class PtrObj, typename CreaFn>
+ bool Register(const IdentifierType& id, const PtrObj& p, CreaFn fn)
+ {
+ return factory.Register(id, p, fn);
+ }
+
+ bool Unregister(const IdentifierType& id)
+ {
+ return factory.Unregister(id);
+ }
+
+ /// Return the registered ID in this Factory
+ std::vector<IdentifierType>& RegisteredIds()
+ {
+ return factory.RegisteredIds();
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id)
+ {
+ MyKey key(id);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1)
+ {
+ MyKey key(id,p1);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2)
+ {
+ MyKey key(id,p1,p2);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3)
+ {
+ MyKey key(id,p1,p2,p3);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
+ {
+ MyKey key(id,p1,p2,p3,p4);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7 )
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9,Parm10 p10)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12, Parm13 p13)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
+ ,key.p13);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
+ ,key.p13,key.p14);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ ProductReturn CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
+ {
+ MyKey key(id,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15);
+ AbstractProduct *pProduct(getPointerToObjectInContainer(getContainerFromKey(key)));
+ if(shouldCreateObject(pProduct))
+ {
+ pProduct = factory.CreateObject(key.id,key.p1,key.p2,key.p3
+ ,key.p4,key.p5,key.p6,key.p7,key.p8,key.p9,key.p10,key.p11,key.p12
+ ,key.p13,key.p14,key.p15);
+ onCreate(pProduct);
+ }
+ onFetch(pProduct);
+ providedObjects[pProduct] = key;
+ return NP::encapsulate(pProduct);
+ }
+
+ /// Use this function to release the object
+ /**
+ * if execution brakes in this function then you tried
+ * to release an object that wasn't provided by this Cache
+ * ... which is bad :-)
+ */
+ void ReleaseObject(ProductReturn &object)
+ {
+ AbstractProduct* pProduct(NP::release(object));
+ typename FetchedObjToKeyMap::iterator itr = providedObjects.find(pProduct);
+ if(itr == providedObjects.end())
+ throw CacheException();
+ onRelease(pProduct);
+ ReleaseObjectFromContainer(getContainerFromKey((*itr).second), pProduct);
+ providedObjects.erase(itr);
+ }
+
+ /// display the cache configuration
+ void displayCacheType()
+ {
+ using namespace std;
+ cout << "############################" << endl;
+ cout << "## Cache configuration" << endl;
+ cout << "## + Encapsulation " << NP::name() << endl;
+ cout << "## + Creating " << CP::name() << endl;
+ cout << "## + Eviction " << EP::name() << endl;
+ cout << "## + Statistics " << SP::name() << endl;
+ cout << "############################" << endl;
+ }
+ };
+} // namespace Loki
+
+#endif // end file guardian
+
diff --git a/shared/loki/CheckReturn.h b/shared/loki/CheckReturn.h
new file mode 100644
index 00000000..fbe63ed0
--- /dev/null
+++ b/shared/loki/CheckReturn.h
@@ -0,0 +1,165 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2007 by Rich Sposato
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef LOKI_CHECK_RETURN_INC_
+#define LOKI_CHECK_RETURN_INC_
+
+// $Id$
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdexcept>
+
+
+namespace Loki
+{
+
+// ----------------------------------------------------------------------------
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class CheckReturn
+///
+/// \par Purpose
+/// C++ provides no mechanism within the language itself to force code to
+/// check the return value from a function call. This simple class provides
+/// a mechanism by which programmers can force calling functions to check the
+/// return value. Or at least make them consciously choose to disregard the
+/// return value. If the calling function fails to use or store the return
+/// value, the destructor calls the OnError policy.
+///
+/// \par Template Parameters
+/// CheckReturn has two template parameters, Value and OnError.
+/// - Value is the return type from the function. CheckReturn stores a copy of
+/// it rather than a reference or pointer since return value could be local to
+/// a function. CheckReturn works best when the return type is a built-in
+/// primitive (bool, int, etc...) a pointer, or an enum (such as an error
+/// condition enum). It can work with other types that have cheap copy
+/// operations.
+/// - OnError is a policy class indicating how to handle the situation when a
+/// caller does not check or copy the returned value. Loki provides some
+/// policy classs and you may also write your own. For example, you can write
+/// a policy to create a message box when the function ignores the return value.
+/// That would quickly tell you places where code ignores the function call.
+/// If your write your own, you only need a templated class or struct with a
+/// public function named "run" that accepts a reference to a const value.
+///
+/// @par Provided Policy Classes
+/// - IgnoreReturnValue Deliberately ignores when the caller ignores the return value.
+/// - TriggerAssert Asserts in debug builds if the caller ignores the return value.
+/// - FprintfStderr Prints out an error message if the caller ignores the return value.
+/// - ThrowTheValue Throws the ignored value as an exception.
+/// - ThrowLogicError Throws a logic_error exception to indicate a programming error.
+////////////////////////////////////////////////////////////////////////////////
+
+
+template<class T>
+struct IgnoreReturnValue
+{
+ static void run(const T&)
+ {
+ /// Do nothing at all.
+ }
+};
+
+template<class T>
+struct ThrowTheValue
+{
+ static void run(const T & value )
+ {
+ throw value;
+ }
+};
+
+template<class T>
+struct ThrowLogicError
+{
+ static void run( const T & )
+ {
+ throw ::std::logic_error( "CheckReturn: return value was not checked.\n" );
+ }
+};
+
+template<class T>
+struct TriggerAssert
+{
+ static void run(const T&)
+ {
+ assert( 0 );
+ }
+};
+
+template<class T>
+struct FprintfStderr
+{
+ static void run(const T&)
+ {
+ fprintf(stderr, "CheckReturn: return value was not checked.\n");
+ }
+};
+
+
+
+template < class Value , template<class> class OnError = TriggerAssert >
+class CheckReturn
+{
+public:
+
+ /// Conversion constructor changes Value type to CheckReturn type.
+ inline CheckReturn( const Value & value ) :
+ m_value( value ), m_checked( false ) {}
+
+ /// Copy-constructor allows functions to call another function within the
+ /// return statement. The other CheckReturn's m_checked flag is set since
+ /// its duty has been passed to the m_checked flag in this one.
+ inline CheckReturn( const CheckReturn & that ) :
+ m_value( that.m_value ), m_checked( false )
+ { that.m_checked = true; }
+
+ /// Destructor checks if return value was used.
+ inline ~CheckReturn( void )
+ {
+ // If m_checked is false, then a function failed to check the
+ // return value from a function call.
+ if (!m_checked)
+ OnError<Value>::run(m_value);
+ }
+
+ /// Conversion operator changes CheckReturn back to Value type.
+ inline operator Value ( void )
+ {
+ m_checked = true;
+ return m_value;
+ }
+
+private:
+ /// Default constructor not implemented.
+ CheckReturn( void );
+
+ /// Copy-assignment operator not implemented.
+ CheckReturn & operator = ( const CheckReturn & that );
+
+ /// Copy of returned value.
+ Value m_value;
+
+ /// Flag for whether calling function checked return value yet.
+ mutable bool m_checked;
+};
+
+// ----------------------------------------------------------------------------
+
+} // namespace Loki
+
+#endif // end file guardian
+
+// $Log$
+
diff --git a/shared/loki/Checker.h b/shared/loki/Checker.h
new file mode 100644
index 00000000..19350679
--- /dev/null
+++ b/shared/loki/Checker.h
@@ -0,0 +1,516 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// The Loki Library
+// Copyright (c) 2008 Rich Sposato
+// The copyright on this file is protected under the terms of the MIT license.
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+//
+// The author makes no representations about the suitability of this software
+// for any purpose. It is provided "as is" without express or implied warranty.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// $Id$
+
+/// @file Checker.h This file provides Loki's Checker facility.
+
+
+// ----------------------------------------------------------------------------
+
+#ifndef LOKI_CHECKER_H_INCLUDED
+#define LOKI_CHECKER_H_INCLUDED
+
+#include <exception> // needed for calls to uncaught_exception.
+#include <assert.h>
+
+
+namespace Loki
+{
+
+/** @par ContractChecker and StaticChecker Overview
+ The ContractChecker and StaticChecker classes have two purposes:
+ - provide a mechanism by which programmers can determine which functions
+ violate class/data invariants,
+ - and determine which exception safety a function provides.
+
+ @par Class & Data Invariants
+ The ContractChecker and StaticChecker define invariants as "expressions that
+ are true for particular data". They uses a function which returns true if all
+ data are valid, and returns false if any datum is invalid. This is called the
+ validator function, and the host class or function provides a pointer to it.
+ The validator could also assert for any invariant which fails rather than
+ return false. If the validator is a static member function, you can use it
+ with checkers in any function, but especially standalone functions and class
+ static functions. If the validator is a non-static member function, you can
+ use it only within non-static member functions.
+
+ @par Exception Safety Levels
+ Years ago, David Abrahams formalized a framework for assessing the exception
+ safety level a function provides. His framework describes three levels of
+ guarantees. Any function which does not provide any of these levels is
+ considered unsafe. ContractChecker and StaticChecker determine a function's
+ safety level through the use of policy classes. Checker's policy classes can
+ show if a function provides any of these three guarantees. Since there is no
+ universal way to detect leaks, this facility provides no mechanism for finding
+ leaks, but users may create their own validators which do. StaticChecker's
+ policy classes only provide direct checking for the no-throw and invariant
+ guarantees. With some finesse, a programmer can write a validator for
+ StaticChecker that checks for the Strong guarantee.
+
+ - No-throw guarantee: A function will not throw any exceptions.
+ - Strong guarantee: A function will not change data if an exception occurs.
+ (Which I call the no-change guarantee.)
+ - Basic guarantee: A function will not leak resources and data will remain
+ in a valid state if an exception occurs. (Which I call either the no-leak
+ or no-break guarantee depending on context.)
+ */
+
+// ----------------------------------------------------------------------------
+
+/** @class CheckForNoThrow
+
+ @par Exception Safety Level:
+ This exception-checking policy class for ContractChecker asserts if an
+ exception exists. Host classes can use this to show that a member function
+ provides the no-throw exception safety guarantees.
+
+ @par Requirements For Host Class:
+ This policy imposes no requirements on a host class.
+ */
+template < class Host >
+class CheckForNoThrow
+{
+public:
+
+ inline explicit CheckForNoThrow( const Host * ) {}
+
+ inline bool Check( const Host * ) const
+ {
+ const bool okay = ( !::std::uncaught_exception() );
+ assert( okay );
+ return okay;
+ }
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class CheckForNoChange
+
+ @par Exception Safety Level:
+ This exception-checking policy class for ContractChecker asserts only if a
+ copy of the host differs from the host object when an exception occurs. Host
+ classes can use this policy to show which member functions provide the strong
+ exception guarantee.
+
+ @par Requirements:
+ This policy requires hosts to provide both the copy-constructor and the
+ equality operator, and is intended for classes with value semantics.
+ equality operator.
+ */
+
+template < class Host >
+class CheckForNoChange
+{
+public:
+
+ inline explicit CheckForNoChange( const Host * host ) :
+ m_compare( *host ) {}
+
+ inline bool Check( const Host * host ) const
+ {
+ const bool okay = ( !::std::uncaught_exception() )
+ || ( m_compare == *host );
+ assert( okay );
+ return okay;
+ }
+
+private:
+ Host m_compare;
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class CheckForNoChangeOrThrow
+
+ @par Exception Safety Level:
+ This exception-checking policy class for ContractChecker asserts either if a
+ copy of the host differs from the original host object, or if an exception
+ occurs. Host classes can use this policy to show which member functions provide
+ the no-throw exception guarantee, and would never change data anyway.
+
+ @par Requirements For Host Class:
+ This policy requires hosts to provide both the copy-constructor and the
+ equality operator, and is intended for classes with value semantics.
+ */
+
+template < class Host >
+class CheckForNoChangeOrThrow
+{
+public:
+
+ inline explicit CheckForNoChangeOrThrow( const Host * host ) :
+ m_compare( *host ) {}
+
+ inline bool Check( const Host * host ) const
+ {
+ bool okay = ( !::std::uncaught_exception() );
+ assert( okay );
+ okay = ( m_compare == *host );
+ assert( okay );
+ return okay;
+ }
+
+private:
+ Host m_compare;
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class CheckForEquality
+
+ @par Exception Safety Level:
+ This exception-checking policy class for ContractChecker asserts if a copy of the host differs from the host object regardless of whether an exception occurs.
+ Host classes can use this policy to show which member functions never change
+ data members, and thereby provide the strong exception safety level by default.
+
+ @par Requirements For Host Class:
+ This policy requires hosts to provide both the copy-constructor and the
+ equality operator, and is intended for classes with value semantics.
+ */
+
+template < class Host >
+class CheckForEquality
+{
+public:
+
+ inline explicit CheckForEquality( const Host * host ) :
+ m_compare( *host ) {}
+
+ inline bool Check( const Host * host ) const
+ {
+ const bool okay = ( m_compare == *host );
+ assert( okay );
+ return okay;
+ }
+
+private:
+ Host m_compare;
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class CheckForNothing
+
+ @par Exception Safety Level:
+ This exception-checking policy class for ContractChecker does nothing when
+ called. Host classes can use this to show which member functions provide
+ neither the strong nor no-throw exception guarantees. The best guarantee such
+ functions can provide is that nothing gets leaked.
+
+ @par Requirements For Host Class:
+ This policy imposes no requirements on a host class.
+ */
+
+template < class Host >
+class CheckForNothing
+{
+public:
+ inline explicit CheckForNothing( const Host * ) {}
+ inline bool Check( const Host * ) const { return true; }
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class ContractChecker
+ This class determines if a function violated any class invariant, but it also
+ determines if a function fulfills its contract with client code. In the
+ "Design by Contract" paradigm, each function has certain pre-conditions and
+ post-conditions which may differ from the class invariants. This asserts if a
+ check for an invariant fails as well as if any pre- or post-condition fails.
+ It also demonstrate which exception safety level a function provides.
+
+ @par Usage
+ -# Implement a function that checks each class invariant. The function must
+ have the signature similar to the Validator type. Something like:
+ "bool Host::IsValid( void ) const;"
+ - The function should return true if everything is okay, but false if
+ something is wrong.
+ - Or it could assert if anything is wrong.
+ - Ideally, it should be private.
+ -# Implement similar functions to check for pre-conditions and post-conditions.
+ Functions which verify pre-conditions and post-conditions do not need to
+ check all class invariants, just conditions specific to certain public
+ functions in the host class.
+ -# Declare some typedef's inside the class declaration like these. Make one
+ typedef for each exception policy you use. I typedef'ed the CheckForNothing
+ policy as CheckInvariants because even if a function can't provide either the
+ no-throw nor the no-change policies, it should still make sure the object
+ remains in a valid state.
+ - typedef ::Loki::ContractChecker< Host, ::Loki::CheckForNoThrow > CheckForNoThrow;
+ - typedef ::Loki::ContractChecker< Host, ::Loki::CheckForNoChange > CheckForNoChange;
+ - typedef ::Loki::ContractChecker< Host, ::Loki::CheckForEquality > CheckForEquality;
+ - typedef ::Loki::ContractChecker< Host, ::Loki::CheckForNothing > CheckInvariants;
+ -# Construct a checker near the top of each member function - except in the
+ validator member function. Pass the this pointer and the address of your
+ validator function into the checker's constructor. You may also pass in pointers
+ to function which check pre- and post-conditions.
+ - If the function never throws, then use the CheckForNoThrow policy.
+ - If the function never changes any data members, then use CheckForEquality
+ policy.
+ - If the function's normal execution flow changes data, but must make sure
+ data remains unchanged when any exceptions occur, then use the
+ CheckForNoChange policy.
+ - Otherwise use the CheckInvariants policy.
+ -# Recompile a debug version of your program, run the program and all the unit
+ tests, and look for which assertions failed.
+ */
+
+template
+<
+ class Host,
+ template < class > class ExceptionPolicy
+>
+class ContractChecker : public ExceptionPolicy< Host >
+{
+ /// Shorthand for the ExceptionPolicy class.
+ typedef ExceptionPolicy< Host > Ep;
+
+public:
+
+ /// Signature for the validation function.
+ typedef bool ( Host:: * Validator )( void ) const;
+
+ /** The constructor makes sure the host is valid at the time the checker
+ was created, thus insuring the host object was not corrupt from the start.
+ @par host Pointer to host object.
+ @par validator Pointer to function that checks class invariants.
+ @par pre Optional pointer to function that checks pre-conditions.
+ @par post Optional pointer to function that checks post-conditions.
+ */
+ inline ContractChecker( const Host * host, Validator validator,
+ Validator pre = 0, Validator post = 0 ) :
+ Ep( host ),
+ m_host( host ),
+ m_validator( validator ),
+ m_pre( pre ),
+ m_post( post )
+ {
+ assert( Check() );
+ if ( 0 != m_pre )
+ assert( ( m_host->*( m_pre ) )() );
+ }
+
+ /** The destructor checks if any Host invariants failed, and then calls the
+ ExceptionPolicy's Check function to determine what to do in case of an
+ exception.
+ */
+ inline ~ContractChecker( void )
+ {
+ assert( Check() );
+ if ( 0 != m_post )
+ assert( ( m_host->*( m_post ) )() );
+ assert( Ep::Check( m_host ) );
+ }
+
+ /** This first checks the invariants for ContractChecker, and then calls the
+ validator function for the host to make sure no class invariants were
+ broken by the host within the Host's member function body. The host
+ member function can call Check directly to verify the object remains valid
+ at any time. This does not care if the pre- and post-condition validator
+ pointers are null since a host class may pass in NULL pointers for either
+ to indicate the pre-conditions or post-conditions are the same as the
+ overall class invariants.
+ */
+ inline bool Check( void ) const
+ {
+ assert( 0 != this );
+ assert( 0 != m_host );
+ assert( 0 != m_validator );
+ // Now that this confirms the pointers to the host and validation
+ // functions are not null, go ahead and validate the host object.
+ const bool okay = ( m_host->*( m_validator ) )();
+ assert( okay );
+ return okay;
+ }
+
+private:
+
+ /// Default constructor is not implemented.
+ ContractChecker( void );
+ /// Copy constructor is not implemented.
+ ContractChecker( const ContractChecker & );
+ /// Copy-assignment operator is not implemented.
+ ContractChecker & operator = ( const ContractChecker & );
+
+ /// Pointer to the host object.
+ const Host * m_host;
+
+ /// Pointer to member function that checks Host object's invariants.
+ Validator m_validator;
+
+ /// Pointer to member function that checks Host object's pre-conditions.
+ Validator m_pre;
+
+ /// Pointer to member function that checks Host object's post-conditions.
+ Validator m_post;
+
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class CheckStaticForNoThrow
+
+ @par Exception Safety Level:
+ This exception-checking policy class for StaticChecker asserts if an exception
+ exists. Functions can use this to show they provide the no-throw exception
+ safety guarantee.
+ */
+class CheckStaticForNoThrow
+{
+public:
+ inline bool Check( void )
+ {
+ const bool okay = !::std::uncaught_exception();
+ assert( okay );
+ return okay;
+ }
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class CheckStaticForNothing
+
+ @par Exception Safety Level:
+ This exception-checking policy class for StaticChecker does nothing when called.
+ Functions can use this to show they might provide the weak exception guarantee.
+ The best guarantee such functions can provide is that nothing gets leaked.
+ */
+class CheckStaticForNothing
+{
+public:
+ inline bool Check( void ) { return true; }
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class StaticChecker
+ This class checks if a function provides the no-throw exception safety level
+ and if the function violated any invariants. Invariants for stand-alone and
+ static functions act as pre-conditions and post-conditions.
+
+ @par Usage
+ -# Implement a function that checks the invariants associated with a function,
+ or with the static data for a class. The function must
+ have the signature similar to the Validator type. Something like:
+ "static bool Host::StaticIsValid( void );" or "bool IsOkay( void );"
+ - The function should return true if everything is okay, but false if
+ something is wrong.
+ - Or it could assert if anything is wrong.
+ -# If the checker is for static functions within a class, declare typedef's
+ inside the class declaration like these. Make one typedef for each policy
+ you use. I typedef'ed the CheckForNothing policy as CheckInvariants because
+ even if a function can't provide the no-throw guarantee, it should still
+ make sure that static data remains in a valid state.
+ - typedef ::Loki::StaticChecker< ::Loki::CheckForNoThrow > CheckStaticForNoThrow;
+ - typedef ::Loki::StaticChecker< ::Loki::CheckForNothing > CheckStaticInvariants;
+ -# Construct a checker near the top of each member function - except in the
+ validator member function. Pass the address of your validator function into
+ the checker's constructor.
+ - If the function never throws, then use the CheckForNoThrow policy.
+ - Otherwise use the CheckInvariants policy.
+ -# Recompile a debug version of your program, run it, and see if an assertion
+ fails.
+ */
+
+template
+<
+ class ExceptionPolicy
+>
+class StaticChecker : public ExceptionPolicy
+{
+ /// Shorthand for the ExceptionPolicy class.
+ typedef ExceptionPolicy Ep;
+
+public:
+
+ /// Signature for the validation function.
+ typedef bool ( * Validator )( void );
+
+ /** The constructor makes sure the host is valid at the time the checker
+ was created, thus insuring the host object was not corrupt from the start.
+ @par validator Pointer to function that checks class invariants.
+ @par pre Optional pointer to function that checks pre-conditions.
+ @par post Optional pointer to function that checks post-conditions.
+ */
+ inline explicit StaticChecker( Validator validator,
+ Validator pre = 0, Validator post = 0 ) :
+ Ep(),
+ m_validator( validator ),
+ m_pre( pre ),
+ m_post( post )
+ {
+ assert( Check() );
+ if ( 0 != m_pre )
+ assert( m_pre() );
+ }
+
+ /** The destructor checks if any Host invariants failed, and then calls the
+ ExceptionPolicy's Check function to determine what to do in case of an
+ exception.
+ */
+ inline ~StaticChecker( void )
+ {
+ assert( Check() );
+ if ( 0 != m_post )
+ assert( m_post() );
+ assert( Ep::Check() );
+ }
+
+ /** This first checks its own invariants, and then calls the validator
+ function to make sure no invariants were broken by the function which
+ created this checker. That function can call Check directly to verify the
+ data remains valid at any time. This does not care if the pre- and post-
+ condition validator pointers are null since a host class may pass in NULL
+ pointers for either to indicate the pre-conditions or post-conditions are
+ the same as the overall class invariants.
+ */
+ inline bool Check( void ) const
+ {
+ assert( 0 != this );
+ assert( 0 != m_validator );
+ // Now that this confirms the pointers to the host and validation
+ // functions are not null, go ahead and validate the host object.
+ const bool okay = m_validator();
+ assert( okay );
+ return okay;
+ }
+
+private:
+
+ /// Default constructor is not implemented.
+ StaticChecker( void );
+ /// Copy constructor is not implemented.
+ StaticChecker( const StaticChecker & );
+ /// Copy-assignment operator is not implemented.
+ StaticChecker & operator = ( const StaticChecker & );
+
+ /// Pointer to member function that checks Host object's invariants.
+ Validator m_validator;
+
+ /// Pointer to member function that checks Host object's pre-conditions.
+ Validator m_pre;
+
+ /// Pointer to member function that checks Host object's post-conditions.
+ Validator m_post;
+
+};
+
+// ----------------------------------------------------------------------------
+
+}; // end namespace Loki
+
+#endif
diff --git a/shared/loki/ConstPolicy.h b/shared/loki/ConstPolicy.h
new file mode 100644
index 00000000..74c9e5aa
--- /dev/null
+++ b/shared/loki/ConstPolicy.h
@@ -0,0 +1,61 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 Richard Sposato
+// Copyright (c) 2006 Peter Kümmel
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The authors make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_CONST_POLICY_INC_
+#define LOKI_CONST_POLICY_INC_
+
+// $Id: ConstPolicy.h 769 2006-10-26 10:58:19Z syntheticpp $
+
+
+namespace Loki
+{
+
+////////////////////////////////////////////////////////////////////////////////
+/// @note These policy classes are used in LockingPtr and SmartPtr to define
+/// how const is propagated from the pointee.
+////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class DontPropagateConst
+///
+/// \ingroup ConstGroup
+/// Don't propagate constness of pointed or referred object.
+////////////////////////////////////////////////////////////////////////////////
+
+ template< class T >
+ struct DontPropagateConst
+ {
+ typedef T Type;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class PropagateConst
+///
+/// \ingroup ConstGroup
+/// Propagate constness of pointed or referred object.
+////////////////////////////////////////////////////////////////////////////////
+
+ template< class T >
+ struct PropagateConst
+ {
+ typedef const T Type;
+ };
+
+// default will not break existing code
+#ifndef LOKI_DEFAULT_CONSTNESS
+#define LOKI_DEFAULT_CONSTNESS ::Loki::DontPropagateConst
+#endif
+
+} // end namespace Loki
+
+#endif // end file guardian
diff --git a/shared/loki/DataGenerators.h b/shared/loki/DataGenerators.h
new file mode 100644
index 00000000..1c8e2df0
--- /dev/null
+++ b/shared/loki/DataGenerators.h
@@ -0,0 +1,113 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Data Generator by Shannon Barber
+// This code DOES NOT accompany the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+//
+// Code covered by the MIT License
+// The author makes no representations about the suitability of this software
+// for any purpose. It is provided "as is" without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_DATAGENERATORS_INC_
+#define LOKI_DATAGENERATORS_INC_
+
+// $Id: DataGenerators.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+#include "Typelist.h"
+
+//Reference version
+
+/************************************************************************************
+// class template GenData
+// Iteratates a Typelist, and invokes the functor GenFunc<T>
+// for each type in the list, passing a functor along the way.
+// The functor is designed to be an insertion iterator which GenFunc<T>
+// can use to output information about the types in the list.
+//
+
+Example Use
+
+template<typename T>
+struct ExtractDataType
+ {
+ some_type operator()()
+ {
+ return create_value_from_type<T>;
+ }
+ };
+
+Loki::IterateTypes<parameter_tl, ExtractDataType> gendata;
+std::vector<some_type> stuff;
+gendata(std::back_inserter(stuff));
+*******************************************************************************/
+namespace Loki
+{
+ namespace TL
+ {
+ template<typename T>
+ struct nameof_type
+ {
+ const char* operator()()
+ {
+ return typeid(T).name();
+ }
+ };
+ template<typename T>
+ struct sizeof_type
+ {
+ size_t operator()()
+ {
+ return sizeof(T);
+ }
+ };
+ template <class TList, template <class> class GenFunc>
+ struct IterateTypes;
+
+ template <class T1, class T2, template <class> class GenFunc>
+ struct IterateTypes<Typelist<T1, T2>, GenFunc>
+ {
+ typedef IterateTypes<T1, GenFunc> head_t;
+ head_t head;
+ typedef IterateTypes<T2, GenFunc> tail_t;
+ tail_t tail;
+ template<class II>
+ void operator()(II ii)
+ {
+ head.operator()(ii);
+ tail.operator()(ii);
+ }
+ };
+
+ template <class AtomicType, template <class> class GenFunc>
+ struct IterateTypes
+ {
+ template<class II>
+ void operator()(II ii)
+ {
+ GenFunc<AtomicType> genfunc;
+ *ii = genfunc();
+ ++ii; //Is this even needed?
+ }
+ };
+
+ template <template <class> class GenFunc>
+ struct IterateTypes<NullType, GenFunc>
+ {
+ template<class II>
+ void operator()(II ii)
+ {}
+ };
+
+ template<typename Types, template <class> class UnitFunc, typename II>
+ void iterate_types(II ii)
+ {
+ Loki::TL::IterateTypes<Types, UnitFunc> it;
+ it(ii);
+ }
+ }//ns TL
+}//ns Loki
+
+#endif // end file guardian
+
diff --git a/shared/loki/EmptyType.h b/shared/loki/EmptyType.h
new file mode 100644
index 00000000..b228e2e8
--- /dev/null
+++ b/shared/loki/EmptyType.h
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_EMPTYTYPE_INC_
+#define LOKI_EMPTYTYPE_INC_
+
+// $Id: EmptyType.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class EmptyType
+// Used as a class type that doesn't hold anything
+// Useful as a strawman class
+////////////////////////////////////////////////////////////////////////////////
+
+ class EmptyType {};
+
+
+ inline bool operator==(const EmptyType&, const EmptyType&)
+ {
+ return true;
+ }
+
+ inline bool operator<(const EmptyType&, const EmptyType&)
+ {
+ return false;
+ }
+
+ inline bool operator>(const EmptyType&, const EmptyType&)
+ {
+ return false;
+ }
+}
+
+#endif // end file guardian
+
diff --git a/shared/loki/Factory.h b/shared/loki/Factory.h
new file mode 100644
index 00000000..c4c3b22a
--- /dev/null
+++ b/shared/loki/Factory.h
@@ -0,0 +1,1084 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// Copyright (c) 2005 by Peter Kuemmel
+// This code DOES NOT accompany the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+//
+// Code covered by the MIT License
+// The authors make no representations about the suitability of this software
+// for any purpose. It is provided "as is" without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_FACTORYPARM_INC_
+#define LOKI_FACTORYPARM_INC_
+
+// $Id: Factory.h 788 2006-11-24 22:30:54Z clitte_bbt $
+
+
+#include "LokiTypeInfo.h"
+#include "Functor.h"
+#include "AssocVector.h"
+#include "SmallObj.h"
+#include "Sequence.h"
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4702)
+//unreachable code if OnUnknownType throws an exception
+#endif
+
+/**
+ * \defgroup FactoriesGroup Factories
+ * \defgroup FactoryGroup Factory
+ * \ingroup FactoriesGroup
+ * \brief Implements a generic object factory.
+ *
+ * <i>The Factory Method pattern is an object-oriented design pattern.
+ * Like other creational patterns, it deals with the problem of creating objects
+ * (products) without specifying the exact class of object that will be created.
+ * Factory Method, one of the patterns from the Design Patterns book, handles
+ * this problem by defining a separate method for creating the objects, which
+ * subclasses can then override to specify the derived type of product that will
+ * be created.
+ * <br>
+ * More generally, the term Factory Method is often used to refer to any method
+ * whose main purpose is creation of objects.</i>
+ * <div ALIGN="RIGHT"><a href="http://en.wikipedia.org/wiki/Factory_method_pattern">
+ * Wikipedia</a></div>
+ *
+ * Loki proposes a generic version of the Factory. Here is a typical use.<br>
+ * <code><br>
+ * 1. Factory< AbstractProduct, int > aFactory;<br>
+ * 2. aFactory.Register( 1, createProductNull );<br>
+ * 3. aFactory.CreateObject( 1 ); <br>
+ * </code><br>
+ * <br>
+ * - 1. The declaration<br>
+ * You want a Factory that produces AbstractProduct.<br>
+ * The client will refer to a creation method through an int.<br>
+ * - 2.The registration<br>
+ * The code that will contribute to the Factory will now need to declare its
+ * ProductCreator by registering them into the Factory.<br>
+ * A ProductCreator is a just a function that will return the right object. ie <br>
+ * <code>
+ * Product* createProductNull()<br>
+ * {<br>
+ * return new Product<br>
+ * }<br>
+ * </code><br>
+ * - 3. The use<br>
+ * Now the client can create object by calling the Factory's CreateObject method
+ * with the right identifier. If the ProductCreator were to have arguments
+ * (<i>ie :Product* createProductParm( int a, int b )</i>)
+ */
+
+namespace Loki
+{
+
+/**
+ * \defgroup FactoryErrorPoliciesGroup Factory Error Policies
+ * \ingroup FactoryGroup
+ * \brief Manages the "Unknown Type" error in an object factory
+ *
+ * \class DefaultFactoryError
+ * \ingroup FactoryErrorPoliciesGroup
+ * \brief Default policy that throws an exception
+ *
+ */
+
+ template <typename IdentifierType, class AbstractProduct>
+ struct DefaultFactoryError
+ {
+ struct Exception : public std::exception
+ {
+ const char* what() const throw() { return "Unknown Type"; }
+ };
+
+ static AbstractProduct* OnUnknownType(IdentifierType)
+ {
+ throw Exception();
+ }
+ };
+
+
+#define LOKI_ENABLE_NEW_FACTORY_CODE
+#ifdef LOKI_ENABLE_NEW_FACTORY_CODE
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+////////////////////////////////////////////////////////////////////////////////
+
+ struct FactoryImplBase
+ {
+ typedef EmptyType Parm1;
+ typedef EmptyType Parm2;
+ typedef EmptyType Parm3;
+ typedef EmptyType Parm4;
+ typedef EmptyType Parm5;
+ typedef EmptyType Parm6;
+ typedef EmptyType Parm7;
+ typedef EmptyType Parm8;
+ typedef EmptyType Parm9;
+ typedef EmptyType Parm10;
+ typedef EmptyType Parm11;
+ typedef EmptyType Parm12;
+ typedef EmptyType Parm13;
+ typedef EmptyType Parm14;
+ typedef EmptyType Parm15;
+ };
+
+ template <typename AP, typename Id, typename TList >
+ struct FactoryImpl;
+
+ template<typename AP, typename Id>
+ struct FactoryImpl<AP, Id, NullType>
+ : public FactoryImplBase
+ {
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id & id ) = 0;
+ };
+template <typename AP, typename Id, typename P1 >
+ struct FactoryImpl<AP,Id, Seq<P1> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1 ) = 0;
+ };
+
+ template<typename AP, typename Id, typename P1,typename P2 >
+ struct FactoryImpl<AP, Id, Seq<P1, P2> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2 ) = 0;
+ };
+
+ template<typename AP, typename Id, typename P1,typename P2,typename P3 >
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3 ) = 0;
+ };
+
+ template<typename AP, typename Id, typename P1,typename P2,typename P3,typename P4 >
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4 ) = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5 >
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5 ) = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6>
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6 )
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7>
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7 )
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8>
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9>
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10>
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11>
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10,
+ Parm11)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11,typename P12>
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10,
+ Parm11,Parm12)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11,typename P12,typename P13>
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10,
+ Parm11,Parm12,Parm13)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11,typename P12,typename P13,typename P14>
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ typedef typename TypeTraits<P14>::ParameterType Parm14;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm8,Parm10,
+ Parm11,Parm12,Parm13,Parm14)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11,typename P12,typename P13,typename P14,typename P15 >
+ struct FactoryImpl<AP, Id, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> >
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ typedef typename TypeTraits<P14>::ParameterType Parm14;
+ typedef typename TypeTraits<P15>::ParameterType Parm15;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10,
+ Parm11,Parm12,Parm13,Parm14,Parm15 )
+ = 0;
+ };
+
+#ifndef LOKI_DISABLE_TYPELIST_MACROS
+
+ template <typename AP, typename Id, typename P1 >
+ struct FactoryImpl<AP,Id, LOKI_TYPELIST_1( P1 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1 ) = 0;
+ };
+
+ template<typename AP, typename Id, typename P1,typename P2 >
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_2( P1, P2 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2 ) = 0;
+ };
+
+ template<typename AP, typename Id, typename P1,typename P2,typename P3 >
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_3( P1, P2, P3 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3 ) = 0;
+ };
+
+ template<typename AP, typename Id, typename P1,typename P2,typename P3,typename P4 >
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_4( P1, P2, P3, P4 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4 ) = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5 >
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_5( P1, P2, P3, P4, P5 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5 ) = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6>
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_6( P1, P2, P3, P4, P5, P6 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6 )
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7>
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_7( P1, P2, P3, P4, P5, P6, P7 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7 )
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8>
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_8( P1, P2, P3, P4, P5, P6, P7, P8 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9>
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_9( P1, P2, P3, P4, P5, P6, P7, P8, P9 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10>
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_10( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11>
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_11( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10,
+ Parm11)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11,typename P12>
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_12( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10,
+ Parm11,Parm12)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11,typename P12,typename P13>
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_13( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10,
+ Parm11,Parm12,Parm13)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11,typename P12,typename P13,typename P14>
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_14( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ typedef typename TypeTraits<P14>::ParameterType Parm14;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm8,Parm10,
+ Parm11,Parm12,Parm13,Parm14)
+ = 0;
+ };
+
+ template<typename AP, typename Id,
+ typename P1,typename P2,typename P3,typename P4,typename P5,
+ typename P6,typename P7,typename P8,typename P9,typename P10,
+ typename P11,typename P12,typename P13,typename P14,typename P15 >
+ struct FactoryImpl<AP, Id, LOKI_TYPELIST_15( P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15 )>
+ : public FactoryImplBase
+ {
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ typedef typename TypeTraits<P14>::ParameterType Parm14;
+ typedef typename TypeTraits<P15>::ParameterType Parm15;
+ virtual ~FactoryImpl() {}
+ virtual AP* CreateObject(const Id& id,Parm1, Parm2, Parm3, Parm4, Parm5,
+ Parm6, Parm7, Parm8, Parm9,Parm10,
+ Parm11,Parm12,Parm13,Parm14,Parm15 )
+ = 0;
+ };
+
+#endif //LOKI_DISABLE_TYPELIST_MACROS
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class Factory
+///
+/// \ingroup FactoryGroup
+/// Implements a generic object factory.
+///
+/// Create functions can have up to 15 parameters.
+///
+/// \par Singleton lifetime when used with Loki::SingletonHolder
+/// Because Factory uses internally Functors which inherits from
+/// SmallObject you must use the singleton lifetime
+/// \code Loki::LongevityLifetime::DieAsSmallObjectChild \endcode
+/// Alternatively you could suppress for Functor the inheritance
+/// from SmallObject by defining the macro:
+/// \code LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT \endcode
+////////////////////////////////////////////////////////////////////////////////
+ template
+ <
+ class AbstractProduct,
+ typename IdentifierType,
+ typename CreatorParmTList = NullType,
+ template<typename, class> class FactoryErrorPolicy = DefaultFactoryError
+ >
+ class Factory : public FactoryErrorPolicy<IdentifierType, AbstractProduct>
+ {
+ typedef FactoryImpl< AbstractProduct, IdentifierType, CreatorParmTList > Impl;
+
+ typedef typename Impl::Parm1 Parm1;
+ typedef typename Impl::Parm2 Parm2;
+ typedef typename Impl::Parm3 Parm3;
+ typedef typename Impl::Parm4 Parm4;
+ typedef typename Impl::Parm5 Parm5;
+ typedef typename Impl::Parm6 Parm6;
+ typedef typename Impl::Parm7 Parm7;
+ typedef typename Impl::Parm8 Parm8;
+ typedef typename Impl::Parm9 Parm9;
+ typedef typename Impl::Parm10 Parm10;
+ typedef typename Impl::Parm11 Parm11;
+ typedef typename Impl::Parm12 Parm12;
+ typedef typename Impl::Parm13 Parm13;
+ typedef typename Impl::Parm14 Parm14;
+ typedef typename Impl::Parm15 Parm15;
+
+ typedef Functor<AbstractProduct*, CreatorParmTList> ProductCreator;
+
+ typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap;
+
+ IdToProductMap associations_;
+
+ public:
+
+ Factory()
+ : associations_()
+ {
+ }
+
+ ~Factory()
+ {
+ associations_.erase(associations_.begin(), associations_.end());
+ }
+
+ bool Register(const IdentifierType& id, ProductCreator creator)
+ {
+ return associations_.insert(
+ typename IdToProductMap::value_type(id, creator)).second != 0;
+ }
+
+ template <class PtrObj, typename CreaFn>
+ bool Register(const IdentifierType& id, const PtrObj& p, CreaFn fn)
+ {
+ ProductCreator creator( p, fn );
+ return associations_.insert(
+ typename IdToProductMap::value_type(id, creator)).second != 0;
+ }
+
+ bool Unregister(const IdentifierType& id)
+ {
+ return associations_.erase(id) != 0;
+ }
+
+ std::vector<IdentifierType> RegisteredIds()
+ {
+ std::vector<IdentifierType> ids;
+ for(typename IdToProductMap::iterator it = associations_.begin();
+ it != associations_.end(); ++it)
+ {
+ ids.push_back(it->first);
+ }
+ return ids;
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7 )
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6,p7 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9 );
+ return this->OnUnknownType(id);
+ }
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9,Parm10 p10)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12, Parm13 p13)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14 );
+ return this->OnUnknownType(id);
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id,
+ Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10,
+ Parm11 p11, Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ return (i->second)( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15 );
+ return this->OnUnknownType(id);
+ }
+
+ };
+
+#else
+
+ template
+ <
+ class AbstractProduct,
+ typename IdentifierType,
+ typename ProductCreator = AbstractProduct* (*)(),
+ template<typename, class>
+ class FactoryErrorPolicy = DefaultFactoryError
+ >
+ class Factory
+ : public FactoryErrorPolicy<IdentifierType, AbstractProduct>
+ {
+ public:
+ bool Register(const IdentifierType& id, ProductCreator creator)
+ {
+ return associations_.insert(
+ typename IdToProductMap::value_type(id, creator)).second != 0;
+ }
+
+ bool Unregister(const IdentifierType& id)
+ {
+ return associations_.erase(id) != 0;
+ }
+
+ AbstractProduct* CreateObject(const IdentifierType& id)
+ {
+ typename IdToProductMap::iterator i = associations_.find(id);
+ if (i != associations_.end())
+ {
+ return (i->second)();
+ }
+ return this->OnUnknownType(id);
+ }
+
+ private:
+ typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap;
+ IdToProductMap associations_;
+ };
+
+#endif //#define ENABLE_NEW_FACTORY_CODE
+
+/**
+ * \defgroup CloneFactoryGroup Clone Factory
+ * \ingroup FactoriesGroup
+ * \brief Creates a copy from a polymorphic object.
+ *
+ * \class CloneFactory
+ * \ingroup CloneFactoryGroup
+ * \brief Creates a copy from a polymorphic object.
+ */
+
+ template
+ <
+ class AbstractProduct,
+ class ProductCreator =
+ AbstractProduct* (*)(const AbstractProduct*),
+ template<typename, class>
+ class FactoryErrorPolicy = DefaultFactoryError
+ >
+ class CloneFactory
+ : public FactoryErrorPolicy<TypeInfo, AbstractProduct>
+ {
+ public:
+ bool Register(const TypeInfo& ti, ProductCreator creator)
+ {
+ return associations_.insert(
+ typename IdToProductMap::value_type(ti, creator)).second != 0;
+ }
+
+ bool Unregister(const TypeInfo& id)
+ {
+ return associations_.erase(id) != 0;
+ }
+
+ AbstractProduct* CreateObject(const AbstractProduct* model)
+ {
+ if (model == NULL)
+ {
+ return NULL;
+ }
+
+ typename IdToProductMap::iterator i =
+ associations_.find(typeid(*model));
+
+ if (i != associations_.end())
+ {
+ return (i->second)(model);
+ }
+ return this->OnUnknownType(typeid(*model));
+ }
+
+ private:
+ typedef AssocVector<TypeInfo, ProductCreator> IdToProductMap;
+ IdToProductMap associations_;
+ };
+
+} // namespace Loki
+
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif // end file guardian
+
diff --git a/shared/loki/Function.h b/shared/loki/Function.h
new file mode 100644
index 00000000..2d0ad4bb
--- /dev/null
+++ b/shared/loki/Function.h
@@ -0,0 +1,373 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2005 Peter Kümmel
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_FUNCTION_INC_
+#define LOKI_FUNCTION_INC_
+
+// $Id: Function.h 841 2008-03-24 23:58:28Z rich_sposato $
+
+
+#define LOKI_ENABLE_FUNCTION
+
+#include <stdexcept>
+
+#include <loki/Functor.h>
+#include <loki/Sequence.h>
+
+namespace Loki
+{
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct Function
+ ///
+ /// \ingroup FunctorGroup
+ /// Allows a boost/TR1 like usage of Functor.
+ ///
+ /// \par Usage
+ ///
+ /// - free functions: e.g. \code Function<int(int,int)> f(&freeFunction);
+ /// \endcode
+ /// - member functions: e.g \code Function<int()> f(&object,&ObjectType::memberFunction);
+ /// \endcode
+ ///
+ /// see also test/Function/FunctionTest.cpp (the modified test program from boost)
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<class R = void()>
+ struct Function;
+
+
+ template<class R>
+ struct Function<R()> : public Functor<R>
+ {
+ typedef Functor<R> FBase;
+
+ Function() : FBase() {}
+
+ Function(const Function& func) : FBase()
+ {
+ if( !func.empty())
+ FBase::operator=(func);
+ }
+
+ // test on emptiness
+ template<class R2>
+ Function(Function<R2()> func) : FBase()
+ {
+ if(!func.empty())
+ FBase::operator=(func);
+ }
+
+ // clear by '= 0'
+ Function(const int i) : FBase()
+ {
+ if(i==0)
+ FBase::clear();
+ else
+ throw std::runtime_error("Loki::Function(const int i): i!=0");
+ }
+
+ template<class Func>
+ Function(Func func) : FBase(func) {}
+
+ template<class Host, class Func>
+ Function(const Host& host, const Func& func) : FBase(host,func) {}
+
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+// macros for the repetitions
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_FUNCTION_BODY \
+ \
+ Function() : FBase() {} \
+ \
+ Function(const Function& func) : FBase() \
+ { \
+ if( !func.empty()) \
+ FBase::operator=(func); \
+ } \
+ \
+ Function(const int i) : FBase() \
+ { \
+ if(i==0) \
+ FBase::clear(); \
+ else \
+ throw std::runtime_error( \
+ "Loki::Function(const int i): i!=0"); \
+ } \
+ \
+ template<class Func> \
+ Function(Func func) : FBase(func) {} \
+ \
+ template<class Host, class Func> \
+ Function(const Host& host, const Func& func): FBase(host,func) {}
+
+
+#define LOKI_FUNCTION_R2_CTOR_BODY \
+ \
+ : FBase() \
+ { \
+ if(!func.empty()) \
+ FBase::operator=(func); \
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////
+// repetitions
+////////////////////////////////////////////////////////////////////////////////
+
+ template<>
+ struct Function<>
+ : public Loki::Functor<>
+ {
+ typedef Functor<> FBase;
+
+ template<class R2>
+ Function(Function<R2()> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY // if compilation breaks here then
+ // Function.h was not included before
+ // Functor.h, check your include order
+ // or define LOKI_ENABLE_FUNCTION
+ };
+
+ template<class R,class P01>
+ struct Function<R(P01)>
+ : public Loki::Functor<R, Seq<P01> >
+ {
+ typedef Functor<R, Seq<P01> > FBase;
+
+ template<class R2,class Q01>
+ Function(Function<R2(Q01)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R,class P01,class P02>
+ struct Function<R(P01,P02)>
+ : public Functor<R, Seq<P01,P02> >
+ {
+ typedef Functor<R, Seq<P01,P02> > FBase;
+
+ template<class R2,class Q01, class Q02>
+ Function(Function<R2(Q01,Q02)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R,class P01,class P02, class P03>
+ struct Function<R(P01,P02,P03)>
+ : public Functor<R, Seq<P01,P02,P03> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03> > FBase;
+
+ template<class R2,class Q01, class Q02,class Q03>
+ Function(Function<R2(Q01,Q02,Q03)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R,class P01,class P02, class P03,class P04>
+ struct Function<R(P01,P02,P03,P04)>
+ : public Functor<R, Seq<P01,P02,P03,P04> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04> > FBase;
+
+ template<class R2,class Q01,class Q02, class Q03,class Q04>
+ Function(Function<R2(Q01,Q02,Q03,Q04)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R,class P01,class P02, class P03,class P04,class P05>
+ struct Function<R(P01,P02,P03,P04,P05)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05> > FBase;
+
+ template<class R2,class Q01,class Q02, class Q03,class Q04,class Q05>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06>
+ struct Function<R(P01,P02,P03,P04,P05,P06)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06> > FBase;
+
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06,class P07>
+ struct Function<R(P01,P02,P03,P04,P05,P06,P07)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07> > FBase;
+
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06,class Q07>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06,class P07, class P08>
+ struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08> > FBase;
+
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06,class Q07, class Q08>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06,class P07, class P08,class P09>
+ struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09 > > FBase;
+
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06,class Q07, class Q08,class Q09>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06,class P07, class P08,class P09,class P10>
+ struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10> > FBase;
+
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06,class Q07, class Q08,class Q09,class Q10>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06,class P07, class P08,class P09,class P10,
+ class P11>
+ struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11> >FBase;
+
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06,class Q07, class Q08,class Q09,class Q10,
+ class Q11>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06,class P07, class P08,class P09,class P10,
+ class P11,class P12>
+ struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12> > FBase;
+
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06,class Q07, class Q08,class Q09,class Q10,
+ class Q11,class Q12>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06,class P07, class P08,class P09,class P10,
+ class P11,class P12, class P13>
+ struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13> > FBase;
+
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06,class Q07, class Q08,class Q09,class Q10,
+ class Q11,class Q12, class Q13>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12,Q13)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06,class P07, class P08,class P09,class P10,
+ class P11,class P12, class P13,class P14>
+ struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14> > FBase;
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06,class Q07, class Q08,class Q09,class Q10,
+ class Q11,class Q12, class Q13,class Q14>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12,Q13,Q14)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+ template<class R, class P01,class P02, class P03,class P04,class P05,
+ class P06,class P07, class P08,class P09,class P10,
+ class P11,class P12, class P13,class P14,class P15>
+ struct Function<R(P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14,P15)>
+ : public Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14,P15> >
+ {
+ typedef Functor<R, Seq<P01,P02,P03,P04,P05,P06,P07,P08,P09,P10,P11,P12,P13,P14,P15> > FBase;
+
+ template<class R2, class Q01,class Q02, class Q03,class Q04,class Q05,
+ class Q06,class Q07, class Q08,class Q09,class Q10,
+ class Q11,class Q12, class Q13,class Q14,class Q15>
+ Function(Function<R2(Q01,Q02,Q03,Q04,Q05,Q06,Q07,Q08,Q09,Q10,Q11,Q12,Q13,Q14,Q15)> func)
+ LOKI_FUNCTION_R2_CTOR_BODY
+
+ LOKI_FUNCTION_BODY
+ };
+
+}// namespace Loki
+
+#endif // end file guardian
+
diff --git a/shared/loki/Functor.h b/shared/loki/Functor.h
new file mode 100644
index 00000000..bcba855d
--- /dev/null
+++ b/shared/loki/Functor.h
@@ -0,0 +1,1789 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_FUNCTOR_INC_
+#define LOKI_FUNCTOR_INC_
+
+// $Id: Functor.h 750 2006-10-17 19:50:02Z syntheticpp $
+
+
+#include "Typelist.h"
+#include "Sequence.h"
+#include "EmptyType.h"
+#include "SmallObj.h"
+#include "TypeTraits.h"
+#include <typeinfo>
+#include <memory>
+
+/// \defgroup FunctorGroup Function objects
+
+#ifndef LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
+//#define LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
+#endif
+
+#ifndef LOKI_FUNCTORS_ARE_COMPARABLE
+//#define LOKI_FUNCTORS_ARE_COMPARABLE
+#endif
+
+
+/// \namespace Loki
+/// All classes of Loki are in the Loki namespace
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl (internal)
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ template <typename R, template <class, class> class ThreadingModel>
+ struct FunctorImplBase
+#ifdef LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
+ {
+#else
+ : public SmallValueObject<ThreadingModel>
+ {
+ inline FunctorImplBase() :
+ SmallValueObject<ThreadingModel>() {}
+ inline FunctorImplBase(const FunctorImplBase&) :
+ SmallValueObject<ThreadingModel>() {}
+#endif
+
+ typedef R ResultType;
+ typedef FunctorImplBase<R, ThreadingModel> FunctorImplBaseType;
+
+ typedef EmptyType Parm1;
+ typedef EmptyType Parm2;
+ typedef EmptyType Parm3;
+ typedef EmptyType Parm4;
+ typedef EmptyType Parm5;
+ typedef EmptyType Parm6;
+ typedef EmptyType Parm7;
+ typedef EmptyType Parm8;
+ typedef EmptyType Parm9;
+ typedef EmptyType Parm10;
+ typedef EmptyType Parm11;
+ typedef EmptyType Parm12;
+ typedef EmptyType Parm13;
+ typedef EmptyType Parm14;
+ typedef EmptyType Parm15;
+
+
+ virtual ~FunctorImplBase()
+ {}
+
+ virtual FunctorImplBase* DoClone() const = 0;
+
+ template <class U>
+ static U* Clone(U* pObj)
+ {
+ if (!pObj) return 0;
+ U* pClone = static_cast<U*>(pObj->DoClone());
+ assert(typeid(*pClone) == typeid(*pObj));
+ return pClone;
+ }
+
+
+#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
+
+ virtual bool operator==(const FunctorImplBase&) const = 0;
+
+#endif
+
+ };
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// macro LOKI_DEFINE_CLONE_FUNCTORIMPL
+// Implements the DoClone function for a functor implementation
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_DEFINE_CLONE_FUNCTORIMPL(Cls) \
+ virtual Cls* DoClone() const { return new Cls(*this); }
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// The base class for a hierarchy of functors. The FunctorImpl class is not used
+// directly; rather, the Functor class manages and forwards to a pointer to
+// FunctorImpl
+// You may want to derive your own functors from FunctorImpl.
+// Specializations of FunctorImpl for up to 15 parameters follow
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, class TList,
+ template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>
+ class FunctorImpl;
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 0 (zero) parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, template <class, class> class ThreadingModel>
+ class FunctorImpl<R, NullType, ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ virtual R operator()() = 0;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 1 parameter
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1>, ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ virtual R operator()(Parm1) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 2 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1, P2>, ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ virtual R operator()(Parm1, Parm2) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 3 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1, P2, P3>, ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ virtual R operator()(Parm1, Parm2, Parm3) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 4 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1, P2, P3, P4>, ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 5 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1, P2, P3, P4, P5>, ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 6 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6>, ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 7 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7>, ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 8 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7, P8>,
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 9 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9>,
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 10 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10>,
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 11 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11>,
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 12 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11, typename P12,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12>,
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11, Parm12) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 13 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11, typename P12, typename P13,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13>,
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 14 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11, typename P12, typename P13, typename P14,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13,
+ P14>,
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ typedef typename TypeTraits<P14>::ParameterType Parm14;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 15 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11, typename P12, typename P13, typename P14,
+ typename P15, template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ Seq<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13,
+ P14, P15>,
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ typedef typename TypeTraits<P14>::ParameterType Parm14;
+ typedef typename TypeTraits<P15>::ParameterType Parm15;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14,
+ Parm15) = 0;
+ };
+
+#ifndef LOKI_DISABLE_TYPELIST_MACROS
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 1 parameter
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_1(P1), ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ virtual R operator()(Parm1) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 2 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_2(P1, P2), ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ virtual R operator()(Parm1, Parm2) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 3 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_3(P1, P2, P3), ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ virtual R operator()(Parm1, Parm2, Parm3) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 4 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_4(P1, P2, P3, P4), ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 5 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_5(P1, P2, P3, P4, P5), ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 6 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_6(P1, P2, P3, P4, P5, P6), ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 7 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_7(P1, P2, P3, P4, P5, P6, P7), ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 8 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_8(P1, P2, P3, P4, P5, P6, P7, P8),
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 9 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_9(P1, P2, P3, P4, P5, P6, P7, P8, P9),
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 10 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R, LOKI_TYPELIST_10(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10),
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 11 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ LOKI_TYPELIST_11(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11),
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 12 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11, typename P12,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ LOKI_TYPELIST_12(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12),
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11, Parm12) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 13 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11, typename P12, typename P13,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ LOKI_TYPELIST_13(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13),
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 14 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11, typename P12, typename P13, typename P14,
+ template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ LOKI_TYPELIST_14(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13,
+ P14),
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ typedef typename TypeTraits<P14>::ParameterType Parm14;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorImpl
+// Specialization for 15 parameters
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, typename P1, typename P2, typename P3, typename P4,
+ typename P5, typename P6, typename P7, typename P8, typename P9,
+ typename P10, typename P11, typename P12, typename P13, typename P14,
+ typename P15, template <class, class> class ThreadingModel>
+ class FunctorImpl<R,
+ LOKI_TYPELIST_15(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13,
+ P14, P15),
+ ThreadingModel>
+ : public Private::FunctorImplBase<R, ThreadingModel>
+ {
+ public:
+ typedef R ResultType;
+ typedef typename TypeTraits<P1>::ParameterType Parm1;
+ typedef typename TypeTraits<P2>::ParameterType Parm2;
+ typedef typename TypeTraits<P3>::ParameterType Parm3;
+ typedef typename TypeTraits<P4>::ParameterType Parm4;
+ typedef typename TypeTraits<P5>::ParameterType Parm5;
+ typedef typename TypeTraits<P6>::ParameterType Parm6;
+ typedef typename TypeTraits<P7>::ParameterType Parm7;
+ typedef typename TypeTraits<P8>::ParameterType Parm8;
+ typedef typename TypeTraits<P9>::ParameterType Parm9;
+ typedef typename TypeTraits<P10>::ParameterType Parm10;
+ typedef typename TypeTraits<P11>::ParameterType Parm11;
+ typedef typename TypeTraits<P12>::ParameterType Parm12;
+ typedef typename TypeTraits<P13>::ParameterType Parm13;
+ typedef typename TypeTraits<P14>::ParameterType Parm14;
+ typedef typename TypeTraits<P15>::ParameterType Parm15;
+ virtual R operator()(Parm1, Parm2, Parm3, Parm4, Parm5, Parm6,
+ Parm7, Parm8, Parm9, Parm10, Parm11, Parm12, Parm13, Parm14,
+ Parm15) = 0;
+ };
+
+#endif //LOKI_DISABLE_TYPELIST_MACROS
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorHandler
+// Wraps functors and pointers to functions
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class ParentFunctor, typename Fun>
+ class FunctorHandler
+ : public ParentFunctor::Impl
+ {
+ typedef typename ParentFunctor::Impl Base;
+
+ public:
+ typedef typename Base::ResultType ResultType;
+ typedef typename Base::Parm1 Parm1;
+ typedef typename Base::Parm2 Parm2;
+ typedef typename Base::Parm3 Parm3;
+ typedef typename Base::Parm4 Parm4;
+ typedef typename Base::Parm5 Parm5;
+ typedef typename Base::Parm6 Parm6;
+ typedef typename Base::Parm7 Parm7;
+ typedef typename Base::Parm8 Parm8;
+ typedef typename Base::Parm9 Parm9;
+ typedef typename Base::Parm10 Parm10;
+ typedef typename Base::Parm11 Parm11;
+ typedef typename Base::Parm12 Parm12;
+ typedef typename Base::Parm13 Parm13;
+ typedef typename Base::Parm14 Parm14;
+ typedef typename Base::Parm15 Parm15;
+
+ FunctorHandler(const Fun& fun) : f_(fun) {}
+
+ LOKI_DEFINE_CLONE_FUNCTORIMPL(FunctorHandler)
+
+
+#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
+
+
+ bool operator==(const typename Base::FunctorImplBaseType& rhs) const
+ {
+ // there is no static information if Functor holds a member function
+ // or a free function; this is the main difference to tr1::function
+ if(typeid(*this) != typeid(rhs))
+ return false; // cannot be equal
+
+ const FunctorHandler& fh = static_cast<const FunctorHandler&>(rhs);
+ // if this line gives a compiler error, you are using a function object.
+ // you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
+ return f_==fh.f_;
+ }
+#endif
+ // operator() implementations for up to 15 arguments
+
+ ResultType operator()()
+ { return f_(); }
+
+ ResultType operator()(Parm1 p1)
+ { return f_(p1); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2)
+ { return f_(p1, p2); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3)
+ { return f_(p1, p2, p3); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
+ { return f_(p1, p2, p3, p4); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
+ { return f_(p1, p2, p3, p4, p5); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6)
+ { return f_(p1, p2, p3, p4, p5, p6); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7)
+ { return f_(p1, p2, p3, p4, p5, p6, p7); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8)
+ { return f_(p1, p2, p3, p4, p5, p6, p7, p8); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
+ { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10)
+ { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11)
+ { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12)
+ { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13)
+ { return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13, Parm14 p14)
+ {
+ return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
+ p14);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
+ {
+ return f_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
+ p14, p15);
+ }
+
+ private:
+ Fun f_;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorHandler
+// Wraps pointers to member functions
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class ParentFunctor, typename PointerToObj,
+ typename PointerToMemFn>
+ class MemFunHandler : public ParentFunctor::Impl
+ {
+ typedef typename ParentFunctor::Impl Base;
+
+ public:
+ typedef typename Base::ResultType ResultType;
+ typedef typename Base::Parm1 Parm1;
+ typedef typename Base::Parm2 Parm2;
+ typedef typename Base::Parm3 Parm3;
+ typedef typename Base::Parm4 Parm4;
+ typedef typename Base::Parm5 Parm5;
+ typedef typename Base::Parm6 Parm6;
+ typedef typename Base::Parm7 Parm7;
+ typedef typename Base::Parm8 Parm8;
+ typedef typename Base::Parm9 Parm9;
+ typedef typename Base::Parm10 Parm10;
+ typedef typename Base::Parm11 Parm11;
+ typedef typename Base::Parm12 Parm12;
+ typedef typename Base::Parm13 Parm13;
+ typedef typename Base::Parm14 Parm14;
+ typedef typename Base::Parm15 Parm15;
+
+ MemFunHandler(const PointerToObj& pObj, PointerToMemFn pMemFn)
+ : pObj_(pObj), pMemFn_(pMemFn)
+ {}
+
+ LOKI_DEFINE_CLONE_FUNCTORIMPL(MemFunHandler)
+
+
+#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
+
+ bool operator==(const typename Base::FunctorImplBaseType& rhs) const
+ {
+ if(typeid(*this) != typeid(rhs))
+ return false; // cannot be equal
+
+ const MemFunHandler& mfh = static_cast<const MemFunHandler&>(rhs);
+ // if this line gives a compiler error, you are using a function object.
+ // you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
+ return pObj_==mfh.pObj_ && pMemFn_==mfh.pMemFn_;
+ }
+#endif
+
+ ResultType operator()()
+ { return ((*pObj_).*pMemFn_)(); }
+
+ ResultType operator()(Parm1 p1)
+ { return ((*pObj_).*pMemFn_)(p1); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2)
+ { return ((*pObj_).*pMemFn_)(p1, p2); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3)
+ { return ((*pObj_).*pMemFn_)(p1, p2, p3); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
+ { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
+ { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6)
+ { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7)
+ { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8)
+ { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
+ { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10)
+ { return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11)
+ {
+ return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
+ p11);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12)
+ {
+ return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
+ p11, p12);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13)
+ {
+ return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
+ p11, p12, p13);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13, Parm14 p14)
+ {
+ return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
+ p11, p12, p13, p14);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
+ {
+ return ((*pObj_).*pMemFn_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
+ p11, p12, p13, p14, p15);
+ }
+
+ private:
+ PointerToObj pObj_;
+ PointerToMemFn pMemFn_;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// TR1 exception
+//////////////////////////////////////////////////////////////////////////////////
+
+#ifdef LOKI_ENABLE_FUNCTION
+
+ class bad_function_call : public std::runtime_error
+ {
+ public:
+ bad_function_call() : std::runtime_error("bad_function_call in Loki::Functor")
+ {}
+ };
+
+#define LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL if(empty()) throw bad_function_call();
+
+#else
+
+#define LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class Functor
+///
+/// \ingroup FunctorGroup
+/// A generalized functor implementation with value semantics
+///
+/// \par Macro: LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT
+/// Define
+/// \code LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT \endcode
+/// to avoid static instantiation/delete
+/// order problems.
+/// It often helps against crashes when using static Functors and multi threading.
+/// Defining also removes problems when unloading Dlls which hosts
+/// static Functor objects.
+///
+/// \par Macro: LOKI_FUNCTORS_ARE_COMPARABLE
+/// To enable the operator== define the macro
+/// \code LOKI_FUNCTORS_ARE_COMPARABLE \endcode
+/// The macro is disabled by default, because it breaks compiling functor
+/// objects which have no operator== implemented, keep in mind when you enable
+/// operator==.
+////////////////////////////////////////////////////////////////////////////////
+ template <typename R = void, class TList = NullType,
+ template<class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>
+ class Functor
+ {
+ public:
+ // Handy type definitions for the body type
+ typedef FunctorImpl<R, TList, ThreadingModel> Impl;
+ typedef R ResultType;
+ typedef TList ParmList;
+ typedef typename Impl::Parm1 Parm1;
+ typedef typename Impl::Parm2 Parm2;
+ typedef typename Impl::Parm3 Parm3;
+ typedef typename Impl::Parm4 Parm4;
+ typedef typename Impl::Parm5 Parm5;
+ typedef typename Impl::Parm6 Parm6;
+ typedef typename Impl::Parm7 Parm7;
+ typedef typename Impl::Parm8 Parm8;
+ typedef typename Impl::Parm9 Parm9;
+ typedef typename Impl::Parm10 Parm10;
+ typedef typename Impl::Parm11 Parm11;
+ typedef typename Impl::Parm12 Parm12;
+ typedef typename Impl::Parm13 Parm13;
+ typedef typename Impl::Parm14 Parm14;
+ typedef typename Impl::Parm15 Parm15;
+
+ // Member functions
+
+ Functor() : spImpl_(0)
+ {}
+
+ Functor(const Functor& rhs) : spImpl_(Impl::Clone(rhs.spImpl_.get()))
+ {}
+
+ Functor(std::auto_ptr<Impl> spImpl) : spImpl_(spImpl)
+ {}
+
+ template <typename Fun>
+ Functor(Fun fun)
+ : spImpl_(new FunctorHandler<Functor, Fun>(fun))
+ {}
+
+ template <class PtrObj, typename MemFn>
+ Functor(const PtrObj& p, MemFn memFn)
+ : spImpl_(new MemFunHandler<Functor, PtrObj, MemFn>(p, memFn))
+ {}
+
+ typedef Impl * (std::auto_ptr<Impl>::*unspecified_bool_type)() const;
+
+ operator unspecified_bool_type() const
+ {
+ return spImpl_.get() ? &std::auto_ptr<Impl>::get : 0;
+ }
+
+ Functor& operator=(const Functor& rhs)
+ {
+ Functor copy(rhs);
+ // swap auto_ptrs by hand
+ Impl* p = spImpl_.release();
+ spImpl_.reset(copy.spImpl_.release());
+ copy.spImpl_.reset(p);
+ return *this;
+ }
+
+#ifdef LOKI_ENABLE_FUNCTION
+
+ bool empty() const
+ {
+ return spImpl_.get() == 0;
+ }
+
+ void clear()
+ {
+ spImpl_.reset(0);
+ }
+#endif
+
+#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
+
+ bool operator==(const Functor& rhs) const
+ {
+ if(spImpl_.get()==0 && rhs.spImpl_.get()==0)
+ return true;
+ if(spImpl_.get()!=0 && rhs.spImpl_.get()!=0)
+ return *spImpl_.get() == *rhs.spImpl_.get();
+ else
+ return false;
+ }
+
+ bool operator!=(const Functor& rhs) const
+ {
+ return !(*this==rhs);
+ }
+#endif
+
+ // operator() implementations for up to 15 arguments
+
+ ResultType operator()() const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)();
+ }
+
+ ResultType operator()(Parm1 p1) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
+ p12);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
+ p12, p13);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13, Parm14 p14) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
+ p12, p13, p14);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15) const
+ {
+ LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL
+ return (*spImpl_)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
+ p12, p13, p14, p15);
+ }
+
+ private:
+ std::auto_ptr<Impl> spImpl_;
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// BindersFirst and Chainer
+//
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ template <class Fctor> struct BinderFirstTraits;
+
+ template <typename R, class TList, template <class, class> class ThreadingModel>
+ struct BinderFirstTraits< Functor<R, TList, ThreadingModel> >
+ {
+ typedef Functor<R, TList, ThreadingModel> OriginalFunctor;
+
+ typedef typename TL::Erase<TList,typename TL::TypeAt<TList, 0>::Result>
+ ::Result
+ ParmList;
+
+ typedef typename TL::TypeAt<TList, 0>::Result OriginalParm1;
+
+ typedef Functor<R, ParmList, ThreadingModel> BoundFunctorType;
+
+ typedef typename BoundFunctorType::Impl Impl;
+
+ };
+
+
+ template<class T>
+ struct BinderFirstBoundTypeStorage;
+
+ template<class T>
+ struct BinderFirstBoundTypeStorage
+ {
+ typedef typename TypeTraits<T>::ParameterType RefOrValue;
+ };
+
+ template <typename R, class TList, template <class, class> class ThreadingModel>
+ struct BinderFirstBoundTypeStorage< Functor<R, TList, ThreadingModel> >
+ {
+ typedef Functor<R, TList, ThreadingModel> OriginalFunctor;
+ typedef const typename TypeTraits<OriginalFunctor>::ReferredType RefOrValue;
+ };
+
+
+ } // namespace Private
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class BinderFirst
+///
+/// \ingroup FunctorGroup
+/// Binds the first parameter of a Functor object to a specific value
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class OriginalFunctor>
+ class BinderFirst
+ : public Private::BinderFirstTraits<OriginalFunctor>::Impl
+ {
+ typedef typename Private::BinderFirstTraits<OriginalFunctor>::Impl Base;
+ typedef typename OriginalFunctor::ResultType ResultType;
+
+ typedef typename OriginalFunctor::Parm1 BoundType;
+
+ typedef typename Private::BinderFirstBoundTypeStorage<
+ typename Private::BinderFirstTraits<OriginalFunctor>
+ ::OriginalParm1>
+ ::RefOrValue
+ BoundTypeStorage;
+
+ typedef typename OriginalFunctor::Parm2 Parm1;
+ typedef typename OriginalFunctor::Parm3 Parm2;
+ typedef typename OriginalFunctor::Parm4 Parm3;
+ typedef typename OriginalFunctor::Parm5 Parm4;
+ typedef typename OriginalFunctor::Parm6 Parm5;
+ typedef typename OriginalFunctor::Parm7 Parm6;
+ typedef typename OriginalFunctor::Parm8 Parm7;
+ typedef typename OriginalFunctor::Parm9 Parm8;
+ typedef typename OriginalFunctor::Parm10 Parm9;
+ typedef typename OriginalFunctor::Parm11 Parm10;
+ typedef typename OriginalFunctor::Parm12 Parm11;
+ typedef typename OriginalFunctor::Parm13 Parm12;
+ typedef typename OriginalFunctor::Parm14 Parm13;
+ typedef typename OriginalFunctor::Parm15 Parm14;
+ typedef EmptyType Parm15;
+
+ public:
+
+ BinderFirst(const OriginalFunctor& fun, BoundType bound)
+ : f_(fun), b_(bound)
+ {}
+
+ LOKI_DEFINE_CLONE_FUNCTORIMPL(BinderFirst)
+
+#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
+
+ bool operator==(const typename Base::FunctorImplBaseType& rhs) const
+ {
+ if(typeid(*this) != typeid(rhs))
+ return false; // cannot be equal
+ // if this line gives a compiler error, you are using a function object.
+ // you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
+ return f_ == ((static_cast<const BinderFirst&> (rhs)).f_) &&
+ b_ == ((static_cast<const BinderFirst&> (rhs)).b_);
+ }
+#endif
+
+ // operator() implementations for up to 15 arguments
+
+ ResultType operator()()
+ { return f_(b_); }
+
+ ResultType operator()(Parm1 p1)
+ { return f_(b_, p1); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2)
+ { return f_(b_, p1, p2); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3)
+ { return f_(b_, p1, p2, p3); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
+ { return f_(b_, p1, p2, p3, p4); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
+ { return f_(b_, p1, p2, p3, p4, p5); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6)
+ { return f_(b_, p1, p2, p3, p4, p5, p6); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7)
+ { return f_(b_, p1, p2, p3, p4, p5, p6, p7); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8)
+ { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
+ { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10)
+ { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11)
+ { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12)
+ { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13)
+ { return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13, Parm14 p14)
+ {
+ return f_(b_, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
+ p14);
+ }
+
+ private:
+ OriginalFunctor f_;
+ BoundTypeStorage b_;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// Binds the first parameter of a Functor object to a specific value
+/// \ingroup FunctorGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class Fctor>
+ typename Private::BinderFirstTraits<Fctor>::BoundFunctorType
+ BindFirst(
+ const Fctor& fun,
+ typename Fctor::Parm1 bound)
+ {
+ typedef typename Private::BinderFirstTraits<Fctor>::BoundFunctorType
+ Outgoing;
+
+ return Outgoing(std::auto_ptr<typename Outgoing::Impl>(
+ new BinderFirst<Fctor>(fun, bound)));
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class Chainer
+///
+/// \ingroup FunctorGroup
+/// Chains two functor calls one after another
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename Fun1, typename Fun2>
+ class Chainer : public Fun2::Impl
+ {
+ typedef Fun2 Base;
+
+ public:
+ typedef typename Base::ResultType ResultType;
+ typedef typename Base::Parm1 Parm1;
+ typedef typename Base::Parm2 Parm2;
+ typedef typename Base::Parm3 Parm3;
+ typedef typename Base::Parm4 Parm4;
+ typedef typename Base::Parm5 Parm5;
+ typedef typename Base::Parm6 Parm6;
+ typedef typename Base::Parm7 Parm7;
+ typedef typename Base::Parm8 Parm8;
+ typedef typename Base::Parm9 Parm9;
+ typedef typename Base::Parm10 Parm10;
+ typedef typename Base::Parm11 Parm11;
+ typedef typename Base::Parm12 Parm12;
+ typedef typename Base::Parm13 Parm13;
+ typedef typename Base::Parm14 Parm14;
+ typedef typename Base::Parm15 Parm15;
+
+ Chainer(const Fun1& fun1, const Fun2& fun2) : f1_(fun1), f2_(fun2) {}
+
+ LOKI_DEFINE_CLONE_FUNCTORIMPL(Chainer)
+
+#ifdef LOKI_FUNCTORS_ARE_COMPARABLE
+
+ bool operator==(const typename Base::Impl::FunctorImplBaseType& rhs) const
+ {
+ if(typeid(*this) != typeid(rhs))
+ return false; // cannot be equal
+ // if this line gives a compiler error, you are using a function object.
+ // you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
+ return f1_ == ((static_cast<const Chainer&> (rhs)).f2_) &&
+ f2_ == ((static_cast<const Chainer&> (rhs)).f1_);
+ }
+#endif
+
+ // operator() implementations for up to 15 arguments
+
+ ResultType operator()()
+ { return f1_(), f2_(); }
+
+ ResultType operator()(Parm1 p1)
+ { return f1_(p1), f2_(p1); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2)
+ { return f1_(p1, p2), f2_(p1, p2); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3)
+ { return f1_(p1, p2, p3), f2_(p1, p2, p3); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4)
+ { return f1_(p1, p2, p3, p4), f2_(p1, p2, p3, p4); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5)
+ { return f1_(p1, p2, p3, p4, p5), f2_(p1, p2, p3, p4, p5); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6)
+ { return f1_(p1, p2, p3, p4, p5, p6), f2_(p1, p2, p3, p4, p5, p6); }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7)
+ {
+ return f1_(p1, p2, p3, p4, p5, p6, p7),
+ f2_(p1, p2, p3, p4, p5, p6, p7);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8)
+ {
+ return f1_(p1, p2, p3, p4, p5, p6, p7, p8),
+ f2_(p1, p2, p3, p4, p5, p6, p7, p8);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9)
+ {
+ return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9),
+ f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10)
+ {
+ return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10),
+ f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11)
+ {
+ return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11),
+ f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12)
+ {
+ return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12),
+ f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13)
+ {
+ return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13),
+ f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13, Parm14 p14)
+ {
+ return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
+ p14),
+ f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
+ p14);
+ }
+
+ ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3, Parm4 p4, Parm5 p5,
+ Parm6 p6, Parm7 p7, Parm8 p8, Parm9 p9, Parm10 p10, Parm11 p11,
+ Parm12 p12, Parm13 p13, Parm14 p14, Parm15 p15)
+ {
+ return f1_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
+ p14, p15),
+ f2_(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
+ p14, p15);
+ }
+
+ private:
+ Fun1 f1_;
+ Fun2 f2_;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// Chains two functor calls one after another
+/// \ingroup FunctorGroup
+////////////////////////////////////////////////////////////////////////////////
+
+
+ template <class Fun1, class Fun2>
+ Fun2 Chain(
+ const Fun1& fun1,
+ const Fun2& fun2)
+ {
+ return Fun2(std::auto_ptr<typename Fun2::Impl>(
+ new Chainer<Fun1, Fun2>(fun1, fun2)));
+ }
+
+} // namespace Loki
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/HierarchyGenerators.h b/shared/loki/HierarchyGenerators.h
new file mode 100644
index 00000000..3fa11ffc
--- /dev/null
+++ b/shared/loki/HierarchyGenerators.h
@@ -0,0 +1,291 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_HIERARCHYGENERATORS_INC_
+#define LOKI_HIERARCHYGENERATORS_INC_
+
+// $Id: HierarchyGenerators.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+#include "Typelist.h"
+#include "TypeTraits.h"
+#include "EmptyType.h"
+
+namespace Loki
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+#pragma warning( push )
+ // 'class1' : base-class 'class2' is already a base-class of 'class3'
+#pragma warning( disable : 4584 )
+#endif // _MSC_VER
+
+////////////////////////////////////////////////////////////////////////////////
+// class template GenScatterHierarchy
+// Generates a scattered hierarchy starting from a typelist and a template
+// Invocation (TList is a typelist, Unit is a template of one arg):
+// GenScatterHierarchy<TList, Unit>
+// The generated class inherits all classes generated by instantiating the
+// template 'Unit' with the types contained in TList
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ // The following type helps to overcome subtle flaw in the original
+ // implementation of GenScatterHierarchy.
+ // The flaw is revealed when the input type list of GenScatterHierarchy
+ // contains more then one element of the same type (e.g. LOKI_TYPELIST_2(int, int)).
+ // In this case GenScatterHierarchy will contain multiple bases of the same
+ // type and some of them will not be reachable (per 10.3).
+ // For example before the fix the first element of Tuple<LOKI_TYPELIST_2(int, int)>
+ // is not reachable in any way!
+ template<class, class>
+ struct ScatterHierarchyTag;
+ }
+
+ template <class TList, template <class> class Unit>
+ class GenScatterHierarchy;
+
+ template <class T1, class T2, template <class> class Unit>
+ class GenScatterHierarchy<Typelist<T1, T2>, Unit>
+ : public GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit>
+ , public GenScatterHierarchy<T2, Unit>
+ {
+ public:
+ typedef Typelist<T1, T2> TList;
+ // Insure that LeftBase is unique and therefore reachable
+ typedef GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> LeftBase;
+ typedef GenScatterHierarchy<T2, Unit> RightBase;
+ template <typename T> struct Rebind
+ {
+ typedef Unit<T> Result;
+ };
+ };
+
+ // In the middle *unique* class that resolve possible ambiguity
+ template <class T1, class T2, template <class> class Unit>
+ class GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit>
+ : public GenScatterHierarchy<T1, Unit>
+ {
+ };
+
+ template <class AtomicType, template <class> class Unit>
+ class GenScatterHierarchy : public Unit<AtomicType>
+ {
+ typedef Unit<AtomicType> LeftBase;
+ template <typename T> struct Rebind
+ {
+ typedef Unit<T> Result;
+ };
+ };
+
+ template <template <class> class Unit>
+ class GenScatterHierarchy<NullType, Unit>
+ {
+ template <typename T> struct Rebind
+ {
+ typedef Unit<T> Result;
+ };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// function template Field
+// Accesses a field in an object of a type generated with GenScatterHierarchy
+// Invocation (obj is an object of a type H generated with GenScatterHierarchy,
+// T is a type in the typelist used to generate H):
+// Field<T>(obj)
+// returns a reference to Unit<T>, where Unit is the template used to generate H
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T, class H>
+ typename H::template Rebind<T>::Result& Field(H& obj)
+ {
+ return obj;
+ }
+
+ template <class T, class H>
+ const typename H::template Rebind<T>::Result& Field(const H& obj)
+ {
+ return obj;
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// function template TupleUnit
+// The building block of tuples
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ struct TupleUnit
+ {
+ T value_;
+ operator T&() { return value_; }
+ operator const T&() const { return value_; }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Tuple
+// Implements a tuple class that holds a number of values and provides field
+// access to them via the Field function (below)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList>
+ struct Tuple : public GenScatterHierarchy<TList, TupleUnit>
+ {
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// helper class template FieldHelper
+// See Field below
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class H, unsigned int i> struct FieldHelper;
+
+ template <class H>
+ struct FieldHelper<H, 0>
+ {
+ typedef typename H::TList::Head ElementType;
+ typedef typename H::template Rebind<ElementType>::Result UnitType;
+
+ enum
+ {
+ isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
+ isConst = TypeTraits<H>::isConst
+ };
+
+ typedef const typename H::LeftBase ConstLeftBase;
+
+ typedef typename Select<isConst, ConstLeftBase,
+ typename H::LeftBase>::Result LeftBase;
+
+ typedef typename Select<isTuple, ElementType,
+ UnitType>::Result UnqualifiedResultType;
+
+ typedef typename Select<isConst, const UnqualifiedResultType,
+ UnqualifiedResultType>::Result ResultType;
+
+ static ResultType& Do(H& obj)
+ {
+ LeftBase& leftBase = obj;
+ return leftBase;
+ }
+ };
+
+ template <class H, unsigned int i>
+ struct FieldHelper
+ {
+ typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
+ typedef typename H::template Rebind<ElementType>::Result UnitType;
+
+ enum
+ {
+ isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
+ isConst = TypeTraits<H>::isConst
+ };
+
+ typedef const typename H::RightBase ConstRightBase;
+
+ typedef typename Select<isConst, ConstRightBase,
+ typename H::RightBase>::Result RightBase;
+
+ typedef typename Select<isTuple, ElementType,
+ UnitType>::Result UnqualifiedResultType;
+
+ typedef typename Select<isConst, const UnqualifiedResultType,
+ UnqualifiedResultType>::Result ResultType;
+
+ static ResultType& Do(H& obj)
+ {
+ RightBase& rightBase = obj;
+ return FieldHelper<RightBase, i - 1>::Do(rightBase);
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// function template Field
+// Accesses a field in an object of a type generated with GenScatterHierarchy
+// Invocation (obj is an object of a type H generated with GenScatterHierarchy,
+// i is the index of a type in the typelist used to generate H):
+// Field<i>(obj)
+// returns a reference to Unit<T>, where Unit is the template used to generate H
+// and T is the i-th type in the typelist
+////////////////////////////////////////////////////////////////////////////////
+
+ template <int i, class H>
+ typename FieldHelper<H, i>::ResultType&
+ Field(H& obj)
+ {
+ return FieldHelper<H, i>::Do(obj);
+ }
+
+// template <int i, class H>
+// const typename FieldHelper<H, i>::ResultType&
+// Field(const H& obj)
+// {
+// return FieldHelper<H, i>::Do(obj);
+// }
+
+////////////////////////////////////////////////////////////////////////////////
+// class template GenLinearHierarchy
+// Generates a linear hierarchy starting from a typelist and a template
+// Invocation (TList is a typelist, Unit is a template of two args):
+// GenScatterHierarchy<TList, Unit>
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ class TList,
+ template <class AtomicType, class Base> class Unit,
+ class Root = EmptyType
+ >
+ class GenLinearHierarchy;
+
+ template
+ <
+ class T1,
+ class T2,
+ template <class, class> class Unit,
+ class Root
+ >
+ class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root>
+ : public Unit< T1, GenLinearHierarchy<T2, Unit, Root> >
+ {
+ };
+
+ template
+ <
+ class T,
+ template <class, class> class Unit,
+ class Root
+ >
+ class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root>
+ : public Unit<T, Root>
+ {
+ };
+
+ template
+ <
+ template <class, class> class Unit,
+ class Root
+ >
+ class GenLinearHierarchy<NullType , Unit, Root>
+ : public Root // is this better: Unit<NullType, Root> ?
+ {
+ };
+
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+#pragma warning( pop )
+#endif
+} // namespace Loki
+
+#endif // end file guardian
+
diff --git a/shared/loki/Key.h b/shared/loki/Key.h
new file mode 100644
index 00000000..4daaa603
--- /dev/null
+++ b/shared/loki/Key.h
@@ -0,0 +1,764 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 by Guillaume Chatelet
+//
+// Code covered by the MIT License
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+//
+// The authors make no representations about the suitability of this software
+// for any purpose. It is provided "as is" without express or implied warranty.
+//
+// This code DOES NOT accompany the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+//
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_KEY_INC_
+#define LOKI_KEY_INC_
+
+// $Id: Key.h 771 2006-10-27 18:05:03Z clitte_bbt $
+
+
+#include <loki/Factory.h>
+
+namespace Loki
+{
+
+ template<
+ class Factory,
+ typename IdentifierType
+ >
+ class Key;
+
+ template<class F, typename I>
+ bool operator==(const Key<F, I> &k1, const Key<F, I> &k2);
+
+ template<class F, typename I>
+ bool operator<(const Key<F, I> &k1, const Key<F, I> &k2);
+
+
+ /**
+ * A Key class
+ */
+ template<
+ class Factory,
+ typename IdentifierType
+ >
+ class Key
+ {
+ typedef typename Factory::Parm1 Parm1;
+ typedef typename Factory::Parm2 Parm2;
+ typedef typename Factory::Parm3 Parm3;
+ typedef typename Factory::Parm4 Parm4;
+ typedef typename Factory::Parm5 Parm5;
+ typedef typename Factory::Parm6 Parm6;
+ typedef typename Factory::Parm7 Parm7;
+ typedef typename Factory::Parm8 Parm8;
+ typedef typename Factory::Parm9 Parm9;
+ typedef typename Factory::Parm10 Parm10;
+ typedef typename Factory::Parm11 Parm11;
+ typedef typename Factory::Parm12 Parm12;
+ typedef typename Factory::Parm13 Parm13;
+ typedef typename Factory::Parm14 Parm14;
+ typedef typename Factory::Parm15 Parm15;
+ public:
+ // member variables
+ int count; // should be const, but constness prevent default copy ctor
+ IdentifierType id;
+ Parm1 p1;
+ Parm2 p2;
+ Parm3 p3;
+ Parm4 p4;
+ Parm5 p5;
+ Parm6 p6;
+ Parm7 p7;
+ Parm8 p8;
+ Parm9 p9;
+ Parm10 p10;
+ Parm11 p11;
+ Parm12 p12;
+ Parm13 p13;
+ Parm14 p14;
+ Parm15 p15;
+
+ // member functions
+ Key() : count(-1)
+ {
+ }
+
+ Key(const IdentifierType& id) : count(0)
+ {
+ this->id = id;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1) : count(1)
+ {
+ this->id = id;
+ this->p1 = p1;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2) : count(2)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3) : count(3)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4) : count(4)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5) : count(5)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6) : count(6)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6, Parm7 &p7 ) : count(7)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ this->p7 = p7;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6, Parm7 &p7, Parm8 &p8) : count(8)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ this->p7 = p7;
+ this->p8 = p8;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9) : count(9)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ this->p7 = p7;
+ this->p8 = p8;
+ this->p9 = p9;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9,Parm10 &p10) : count(10)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ this->p7 = p7;
+ this->p8 = p8;
+ this->p9 = p9;
+ this->p10 = p10;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10,
+ Parm11 &p11) : count(11)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ this->p7 = p7;
+ this->p8 = p8;
+ this->p9 = p9;
+ this->p10 = p10;
+ this->p11 = p11;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10,
+ Parm11 &p11, Parm12 &p12) : count(12)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ this->p7 = p7;
+ this->p8 = p8;
+ this->p9 = p9;
+ this->p10 = p10;
+ this->p11 = p11;
+ this->p12 = p12;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10,
+ Parm11 &p11, Parm12 &p12, Parm13 &p13) : count(13)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ this->p7 = p7;
+ this->p8 = p8;
+ this->p9 = p9;
+ this->p10 = p10;
+ this->p11 = p11;
+ this->p12 = p12;
+ this->p13 = p13;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10,
+ Parm11 &p11, Parm12 &p12, Parm13 &p13, Parm14 &p14) : count(14)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ this->p7 = p7;
+ this->p8 = p8;
+ this->p9 = p9;
+ this->p10 = p10;
+ this->p11 = p11;
+ this->p12 = p12;
+ this->p13 = p13;
+ this->p14 = p14;
+ }
+
+ Key(const IdentifierType& id,
+ Parm1 &p1, Parm2 &p2, Parm3 &p3, Parm4 &p4, Parm5 &p5,
+ Parm6 &p6, Parm7 &p7, Parm8 &p8, Parm9 &p9, Parm10 &p10,
+ Parm11 &p11, Parm12 &p12, Parm13 &p13, Parm14 &p14, Parm15 &p15) : count(15)
+ {
+ this->id = id;
+ this->p1 = p1;
+ this->p2 = p2;
+ this->p3 = p3;
+ this->p4 = p4;
+ this->p5 = p5;
+ this->p6 = p6;
+ this->p7 = p7;
+ this->p8 = p8;
+ this->p9 = p9;
+ this->p10 = p10;
+ this->p11 = p11;
+ this->p12 = p12;
+ this->p13 = p13;
+ this->p14 = p14;
+ this->p15 = p15;
+ }
+
+ template<class F, typename I>
+ friend bool operator==(const Key<F, I> &k1, const Key<F, I> &k2);
+
+ template<class F, typename I>
+ friend bool operator<(const Key<F, I> &k1, const Key<F, I> &k2);
+ };
+
+
+ template<class F, typename I>
+ bool operator==(const Key<F, I> &k1, const Key<F, I> &k2)
+ {
+ if( k1.count != k2.count )
+ return false;
+ switch(k1.count){
+ case -1:
+ return true;
+ case 0:
+ if( k1.id == k2.id )
+ return true;
+ else
+ return false;
+ case 1:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) )
+ return true;
+ else
+ return false;
+ case 2:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) )
+ return true;
+ else
+ return false;
+ case 3:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) )
+ return true;
+ else
+ return false;
+ case 4:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) )
+ return true;
+ else
+ return false;
+ case 5:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) )
+ return true;
+ else
+ return false;
+ case 6:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) )
+ return true;
+ else
+ return false;
+ case 7:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) &&
+ (k1.p7 == k2.p7) )
+ return true;
+ else
+ return false;
+ case 8:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) &&
+ (k1.p7 == k2.p7) &&
+ (k1.p8 == k2.p8) )
+ return true;
+ else
+ return false;
+ case 9:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) &&
+ (k1.p7 == k2.p7) &&
+ (k1.p8 == k2.p8) &&
+ (k1.p9 == k2.p9) )
+ return true;
+ else
+ return false;
+ case 10:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) &&
+ (k1.p7 == k2.p7) &&
+ (k1.p8 == k2.p8) &&
+ (k1.p9 == k2.p9) &&
+ (k1.p10 == k2.p10) )
+ return true;
+ else
+ return false;
+ case 11:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) &&
+ (k1.p7 == k2.p7) &&
+ (k1.p8 == k2.p8) &&
+ (k1.p9 == k2.p9) &&
+ (k1.p10 == k2.p10) &&
+ (k1.p11 == k2.p11) )
+ return true;
+ else
+ return false;
+ case 12:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) &&
+ (k1.p7 == k2.p7) &&
+ (k1.p8 == k2.p8) &&
+ (k1.p9 == k2.p9) &&
+ (k1.p10 == k2.p10) &&
+ (k1.p11 == k2.p11) &&
+ (k1.p12 == k2.p12) )
+ return true;
+ else
+ return false;
+ case 13:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) &&
+ (k1.p7 == k2.p7) &&
+ (k1.p8 == k2.p8) &&
+ (k1.p9 == k2.p9) &&
+ (k1.p10 == k2.p10) &&
+ (k1.p11 == k2.p11) &&
+ (k1.p12 == k2.p12) &&
+ (k1.p13 == k2.p13) )
+ return true;
+ else
+ return false;
+ case 14:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) &&
+ (k1.p7 == k2.p7) &&
+ (k1.p8 == k2.p8) &&
+ (k1.p9 == k2.p9) &&
+ (k1.p10 == k2.p10) &&
+ (k1.p11 == k2.p11) &&
+ (k1.p12 == k2.p12) &&
+ (k1.p13 == k2.p13) &&
+ (k1.p14 == k2.p14) )
+ return true;
+ else
+ return false;
+ case 15:
+ if( (k1.id == k2.id) &&
+ (k1.p1 == k2.p1) &&
+ (k1.p2 == k2.p2) &&
+ (k1.p3 == k2.p3) &&
+ (k1.p4 == k2.p4) &&
+ (k1.p5 == k2.p5) &&
+ (k1.p6 == k2.p6) &&
+ (k1.p7 == k2.p7) &&
+ (k1.p8 == k2.p8) &&
+ (k1.p9 == k2.p9) &&
+ (k1.p10 == k2.p10) &&
+ (k1.p11 == k2.p11) &&
+ (k1.p12 == k2.p12) &&
+ (k1.p13 == k2.p13) &&
+ (k1.p14 == k2.p14) &&
+ (k1.p15 == k2.p15) )
+ return true;
+ else
+ return false;
+ default:
+ return false;
+ }
+ }
+
+
+
+ template<class F, typename I>
+ bool operator<(const Key<F, I> &k1, const Key<F, I> &k2)
+ {
+ if( k1.count < k2.count )
+ return true;
+ switch(k1.count){
+ case -1:
+ return false;
+ case 0:
+ if( k1.id < k2.id )
+ return true;
+ else
+ return false;
+ case 1:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) )
+ return true;
+ else
+ return false;
+ case 2:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) )
+ return true;
+ else
+ return false;
+ case 3:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) )
+ return true;
+ else
+ return false;
+ case 4:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) )
+ return true;
+ else
+ return false;
+ case 5:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) )
+ return true;
+ else
+ return false;
+ case 6:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) )
+ return true;
+ else
+ return false;
+ case 7:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) ||
+ (k1.p7 < k2.p7) )
+ return true;
+ else
+ return false;
+ case 8:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) ||
+ (k1.p7 < k2.p7) ||
+ (k1.p8 < k2.p8) )
+ return true;
+ else
+ return false;
+ case 9:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) ||
+ (k1.p7 < k2.p7) ||
+ (k1.p8 < k2.p8) ||
+ (k1.p9 < k2.p9) )
+ return true;
+ else
+ return false;
+ case 10:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) ||
+ (k1.p7 < k2.p7) ||
+ (k1.p8 < k2.p8) ||
+ (k1.p9 < k2.p9) ||
+ (k1.p10 < k2.p10) )
+ return true;
+ else
+ return false;
+ case 11:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) ||
+ (k1.p7 < k2.p7) ||
+ (k1.p8 < k2.p8) ||
+ (k1.p9 < k2.p9) ||
+ (k1.p10 < k2.p10) ||
+ (k1.p11 < k2.p11) )
+ return true;
+ else
+ return false;
+ case 12:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) ||
+ (k1.p7 < k2.p7) ||
+ (k1.p8 < k2.p8) ||
+ (k1.p9 < k2.p9) ||
+ (k1.p10 < k2.p10) ||
+ (k1.p11 < k2.p11) ||
+ (k1.p12 < k2.p12) )
+ return true;
+ else
+ return false;
+ case 13:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) ||
+ (k1.p7 < k2.p7) ||
+ (k1.p8 < k2.p8) ||
+ (k1.p9 < k2.p9) ||
+ (k1.p10 < k2.p10) ||
+ (k1.p11 < k2.p11) ||
+ (k1.p12 < k2.p12) ||
+ (k1.p13 < k2.p13) )
+ return true;
+ else
+ return false;
+ case 14:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) ||
+ (k1.p7 < k2.p7) ||
+ (k1.p8 < k2.p8) ||
+ (k1.p9 < k2.p9) ||
+ (k1.p10 < k2.p10) ||
+ (k1.p11 < k2.p11) ||
+ (k1.p12 < k2.p12) ||
+ (k1.p13 < k2.p13) ||
+ (k1.p14 < k2.p14) )
+ return true;
+ else
+ return false;
+ case 15:
+ if( (k1.id < k2.id) ||
+ (k1.p1 < k2.p1) ||
+ (k1.p2 < k2.p2) ||
+ (k1.p3 < k2.p3) ||
+ (k1.p4 < k2.p4) ||
+ (k1.p5 < k2.p5) ||
+ (k1.p6 < k2.p6) ||
+ (k1.p7 < k2.p7) ||
+ (k1.p8 < k2.p8) ||
+ (k1.p9 < k2.p9) ||
+ (k1.p10 < k2.p10) ||
+ (k1.p11 < k2.p11) ||
+ (k1.p12 < k2.p12) ||
+ (k1.p13 < k2.p13) ||
+ (k1.p14 < k2.p14) ||
+ (k1.p15 < k2.p15) )
+ return true;
+ else
+ return false;
+ default:
+ return false;
+ }
+ }
+
+
+
+} // namespace Loki
+
+#endif // end file guardian
+
diff --git a/shared/loki/LevelMutex.h b/shared/loki/LevelMutex.h
new file mode 100644
index 00000000..c048000f
--- /dev/null
+++ b/shared/loki/LevelMutex.h
@@ -0,0 +1,1211 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// LevelMutex facility for the Loki Library
+// Copyright (c) 2008 Richard Sposato
+// The copyright on this file is protected under the terms of the MIT license.
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+//
+// The author makes no representations about the suitability of this software
+// for any purpose. It is provided "as is" without express or implied warranty.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// $Id$
+
+/// @file LevelMutex.h Defines classes and functions for LevelMutex facility.
+
+#ifndef LOKI_LEVEL_MUTEX_H_INCLUDED
+#define LOKI_LEVEL_MUTEX_H_INCLUDED
+
+
+// ----------------------------------------------------------------------------
+
+#include <vector>
+#include <assert.h>
+#include <time.h>
+
+#if defined( _MSC_VER )
+ #include <Windows.h>
+#else
+ #include <pthread.h>
+#endif
+
+#if !defined(_WIN32) && !defined(_WIN64)
+ #include <unistd.h> // declares sleep under Linux
+#endif
+
+/** @par thread_local Keyword
+ The mutexes require compilers to provide thread local storage - meaning each
+ thread gets its own copy of the data. The next version of C++ will have a
+ new keyword, thread_local for that purpose. Some existing compilers already
+ provide thread local storage using different syntax, so these lines use
+ thread_local to mimic that syntax. If your compiler provides thread local
+ storage but using different syntax besides "thread_local", you may want to
+ modify these lines. If your compiler does not support thread local storage,
+ you can't use LevelMutex.
+ */
+#ifndef LOKI_THREAD_LOCAL
+ #if defined( _MSC_VER )
+ #if ( _MSC_VER >= 1300 )
+ #define LOKI_THREAD_LOCAL __declspec( thread )
+ #else
+ #error "Only Visual Studio versions 7.0 and after supported."
+ #endif
+
+ #elif ( __GNUC__ )
+ #define LOKI_THREAD_LOCAL __thread
+
+ #else
+ #warning "Check if your compiler provides thread local storage."
+ #define LOKI_THREAD_LOCAL thread_local
+ #endif
+#endif
+
+#if defined( DEBUG ) || defined( _DEBUG )
+ #define LOKI_MUTEX_DEBUG_CODE( x ) x
+#else
+ #define LOKI_MUTEX_DEBUG_CODE( x )
+#endif
+
+
+namespace Loki
+{
+
+
+// ----------------------------------------------------------------------------
+
+class MutexErrors
+{
+public:
+
+ /// @enum Type Possible error conditions detected by LevelMutex functions.
+ enum Type
+ {
+ Success = 0, ///< Operation occurred correctly.
+ NoProblem, ///< Pre-lock and pre-unlock checks passed.
+ WrongLevel, ///< All mutexes in container must have same level.
+ LevelTooLow, ///< Trying to unlock a mutex lower than current level.
+ LevelTooHigh, ///< Trying to lock a mutex higher than current level.
+ TryFailed, ///< TryLock call failed to lock mutex.
+ NullMutexPointer, ///< Container has a NULL pointer in it.
+ DuplicateMutex, ///< Container must have unique pointers - no duplicates.
+ EmptyContainer, ///< Container must have at least 1 pointer in it.
+ AlreadyLocked, ///< TryLock call failed because mutex already locked.
+ WasntLocked, ///< Unlock failed because mutex was not even locked.
+ NotRecentLock, ///< Mutex in container was not recently locked by this thread.
+ NotLockedByThread, ///< Can't unlock a mutex not locked by this thread.
+ MultiUnlockFailed, ///< MultiUnlock can't unlock at least 1 mutex in container.
+ TimedOut, ///< Wait time elapsed without locking mutex.
+ TooMuchRecursion, ///< Tried to relock a PThread mutex which is not re-entrant.
+ NotInitialized, ///< Tried to lock a PThread mutex which did not get setup.
+ AlreadyInitialized, ///< PThread mutex initialized before ctor called.
+ InvalidAttribute, ///< PThread mutex improperly initialized.
+ InvalidAddress, ///< Bad pointer used to initialize a PThread mutex.
+ ExceptionThrown, ///< Exception caught in mutex operation.
+ MayDeadlock, ///< Locking this mutex may cause a deadlock.
+ OtherError ///< Unknown error occurred.
+ };
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class LevelMutexInfo
+ This monolithic base class stores common info for a template class used to
+ control mutexes. The template class, LevelMutex, is policy-based class.
+
+ @par Implementation
+ Each thread has a list of mutexes it locked. When a mutex first gets locked, it
+ gets added to the head of the list. If locked again, LevelMutex merely increments
+ a count. When unlocked, the count gets decremented until it reaches zero, and
+ then it gets removed from the list. Each mutex has a pointer to the mutex most
+ recently locked by the current thread. The current level of a thread is always
+ the level of the most recently locked mutex, or UnlockedLevel if the thread does
+ not have any mutexes locked now. A mutex is considered "recently" locked if it is at
+ the head of the list, or the same level as the current mutex and also locked by the
+ current thread.
+
+ @par Class Invariants
+ This class maintains invariants for each LevelMutexInfo so that no function
+ calls corrupt a mutex. Each function makes a call to IsValid at the start so
+ that LevelMutex knows it acts on valid internal data. Many functions call
+ IsValid again when they return to insure the function did not leave any data in
+ an invalid state. The exit call to IsValid occurs through a tiny helper class
+ called Checker to insure all data remain valid even when exceptions occur.
+ Another helper class, MutexUndoer, unlocks mutexes in a container if an
+ exception occurs during calls to MultiLock.
+
+ @par Error Results
+ Many functions return an enum value to indicate an error status. Many enum values
+ indicate errors detected within LevelMutex, but some indicate errors found in policy
+ classes, SpinLevelMutex and SleepLevelMutex.
+ */
+
+class LevelMutexInfo
+{
+public:
+
+ /** Level for thread that has not locked any mutex. Maximum possible level
+ for a mutex is UnlockedLevel-1; No mutex may have a level of UnlockedLevel.
+ */
+ static const unsigned int UnlockedLevel = 0xFFFFFFFF;
+
+ /// Container for locking multiple mutexes at once.
+ typedef ::std::vector< volatile LevelMutexInfo * > MutexContainer;
+ typedef MutexContainer::iterator LevelMutexContainerIter;
+ typedef MutexContainer::const_iterator LevelMutexContainerCIter;
+ typedef MutexContainer::reverse_iterator LevelMutexContainerRIter;
+ typedef MutexContainer::const_reverse_iterator LevelMutexContainerCRIter;
+
+ /** Locks several mutexes at once. Requires O(m + n*n) actions where m is the
+ number of mutexes currently locked by the thread and n is the number of mutexes
+ in the container. This provides strong exception safety. If an exception occurs,
+ any mutexes that were locked during this call will get unlocked.
+ @param mutexes Container of pointers to mutexes. Container must have at
+ least 1 mutex, all mutexes must have the same level, no NULL pointers, and all
+ mutexes must not exceed the thread's current level. This sorts the container
+ by address order.
+ @return Enum value indicating success or error.
+ */
+ static MutexErrors::Type MultiLock( MutexContainer & mutexes );
+
+ /** Locks several mutexes at once. Requires O(m + n*n + n*t) actions where m is
+ the number of mutexes currently locked by the thread, n is the number of mutexes
+ in the container, and t is the wait time for each mutex. This provides strong
+ exception safety. If an exception occurs, any mutexes that were locked during
+ this call will ge unlocked.
+ @param mutexes Container of pointers to mutexes. Container must have at
+ least 1 mutex, all mutexes must have the same level, no NULL pointers, and all
+ mutexes must not exceed the thread's current level. This sorts the container
+ by address order.
+ @param milliSeconds Amount of time to wait for each mutex.
+ @return Enum value indicating success or error.
+ */
+ static MutexErrors::Type MultiLock( MutexContainer & mutexes,
+ unsigned int milliSeconds );
+
+ /** Unlocks several mutexes at once. Requires O(m) actions where m is the number of
+ mutexes in the container. This provides strong exception safety. If an exception
+ occurs when unlocking one mutex, other mutexes in the container get unlocked anyway.
+ @param mutexes Container of pointers to mutexes. Container must have at least 1
+ mutex, all mutexes must have the same level, no NULL pointers, and all mutexes must
+ be locked by the current thread. This sorts the container dby address order.
+ @return Enum value indicating success or error.
+ */
+ static MutexErrors::Type MultiUnlock( MutexContainer & mutexes );
+
+ /** Gives pointer to most recently locked mutex, or NULL if nothing locked.
+ The pointer is for a const mutex so the mutex can't be modified inappropriately.
+ The pointer is for a volatile mutex so callers can call volatile member
+ functions to get info about the mutex.
+ */
+ static const volatile LevelMutexInfo * GetCurrentMutex( void );
+
+ /// Returns the level of this mutex.
+ inline unsigned int GetLevel( void ) const volatile { return m_level; }
+
+ /// Returns true if this mutex was locked at least once.
+ inline bool IsLocked( void ) const volatile { return ( 0 < m_count ); }
+
+ /// Returns count of how many times this mutex got locked.
+ inline unsigned int GetLockCount( void ) const volatile { return m_count; }
+
+ /// Returns pointer to mutex previously locked by the thread which locked this.
+ inline const volatile LevelMutexInfo * GetPrevious( void ) const volatile
+ {
+ return m_previous;
+ }
+
+ /** Tries to lock mutex, and returns immediately if mutex already locked by
+ another thread. It will return immediately with a value of AlreadyLocked
+ if the mutex was locked by a different thread. It may throw an exception
+ or assert when errors occur if the ErrorPolicy class implements that behavior.
+ @return An error condition if any occurred, else Success.
+ */
+ virtual MutexErrors::Type TryLock( void ) volatile = 0;
+
+ /** Blocking call will attempt to lock mutex and wait until it can lock.
+ This may throw an exception if the lock failed or an error occurred - if
+ that is what the error policy specifies.
+ @return An error condition if any occurred, else Success.
+ */
+ virtual MutexErrors::Type Lock( void ) volatile = 0;
+
+ /** Attempts to lock mutex, but only waits for a limited amount of time
+ before it gives up. Will return quickly if an error occurs before any
+ attempt to lock. This may throw an exception if the lock failed or an
+ error occurred - if that is what the error policy specifies.
+ @param milliSeconds How long to wait.
+ @return An error condition if any occurred, else Success.
+ */
+ virtual MutexErrors::Type Lock( unsigned int milliSeconds ) volatile = 0;
+
+ /** Unlocks the mutex, or returns an error condition. This may throw an
+ exception if the lock failed or an error occurred - if that is what the
+ error policy specifies.
+ @return An error condition if any occurred, else Success.
+ */
+ virtual MutexErrors::Type Unlock( void ) volatile = 0;
+
+ /** Returns true if this mutex was locked by current thread, and level is the same
+ as the current thread's level. Which means this was the most recently locked
+ mutex, or it was locked along with several others of the same level recently.
+ */
+ bool IsRecentLock( void ) const volatile;
+
+ /** Returns true if this mutex was locked within the last count mutexes.
+ @param count How many recent mutexes to look through to find this mutex.
+ */
+ bool IsRecentLock( unsigned int count ) const volatile;
+
+ /// Returns true if this was locked by current thread.
+ bool IsLockedByCurrentThread( void ) const volatile;
+
+ /// Returns true if this was locked by another thread.
+ bool IsLockedByAnotherThread( void ) const volatile;
+
+protected:
+
+ /** @class Checker Performs validity check on mutex to insure no class invariants
+ were violated inside any member function. This class only gets used in debug
+ builds, and any instance of it gets optimized away in release builds. A checker
+ is created inside many of member functions so that it's destructor gets called
+ when the function exits. It determines if any class invariants were violated
+ during the function call.
+ */
+ class Checker
+ {
+ public:
+ inline explicit Checker( const volatile LevelMutexInfo * mutex ) :
+ m_mutex( mutex ) {}
+ inline ~Checker( void ) { m_mutex->IsValid(); }
+ private:
+ Checker( void );
+ Checker( const Checker & );
+ Checker & operator = ( const Checker & );
+ const volatile LevelMutexInfo * m_mutex;
+ };
+
+ /** @class MutexUndoer
+ Undoes actions by MultiLock if an exception occurs. It keeps track of
+ which mutexes in a container got locked, and if an exception occurs, then
+ the destructor unlocks them. If MultiLock succeeds, then it cancels the
+ undoer so nothing gets unlocked inadvertently.
+ */
+ class MutexUndoer
+ {
+ public:
+
+ explicit MutexUndoer( MutexContainer & mutexes );
+ ~MutexUndoer( void );
+ void SetPlace( LevelMutexContainerIter & here );
+ void Cancel( void );
+
+ private:
+
+ MutexUndoer( void );
+ MutexUndoer( const MutexUndoer & );
+ MutexUndoer & operator = ( const MutexUndoer & );
+
+ MutexContainer & m_mutexes;
+ LevelMutexContainerIter m_here;
+ };
+
+ /** Returns true if linked-list of locked mutexes in this thread is valid.
+ Which means the list has no loops, and each previous mutex on the list has a
+ higher or same level as the current mutex. Called by IsValid.
+ */
+ static bool IsValidList( void );
+
+ /** This is the only available constructor, and it forces any derived class to set
+ a level for each mutex.
+ */
+ explicit LevelMutexInfo( unsigned int level );
+
+ /// The destructor only gets called by the derived class.
+ virtual ~LevelMutexInfo( void );
+
+ MutexErrors::Type PreLockCheck( bool forTryLock ) volatile;
+
+ MutexErrors::Type PreUnlockCheck( void ) volatile;
+
+ /** This gets called after each call to DoLock and DoTryLock to make sure the data
+ members in this object get set correctly.
+ */
+ void PostLock( void ) volatile;
+
+ /// Gets called just before an attempt to unlock a mutex.
+ void PreUnlock( void ) volatile;
+
+ /// Called to relock a mutex already locked by the current thread.
+ void IncrementCount( void ) volatile;
+
+ /// Called to unlock a mutex locked multiple times by the current thread.
+ void DecrementCount( void ) volatile;
+
+ /** Returns true if no class invariant broken, otherwise asserts. This function
+ only gets called in debug builds.
+ */
+ bool IsValid( void ) const volatile;
+
+private:
+
+ /// Copy constructor is not implemented.
+ LevelMutexInfo( const LevelMutexInfo & );
+ /// Copy-assignment operator is not implemented.
+ LevelMutexInfo & operator = ( const LevelMutexInfo & );
+
+ /** Called only by MultiLock & MultiUnlock to pass a result through an
+ error checking policy.
+ @param result What error condition to check.
+ @return Result or assertion or an exception - depending on error policy.
+ */
+ virtual MutexErrors::Type DoErrorCheck( MutexErrors::Type result ) const volatile = 0;
+
+ /// Called only by MultiLock to Lock each particular mutex within a container.
+ virtual MutexErrors::Type LockThis( void ) volatile = 0;
+
+ /** Called only by MultiLock to lock each particular mutex within a container.
+ @param milliSeconds How much time to wait before giving up on locking a mutex.
+ */
+ virtual MutexErrors::Type LockThis( unsigned int milliSeconds ) volatile = 0;
+
+ /// Called only by MultiUnlock to unlock each particular mutex within a container.
+ virtual MutexErrors::Type UnlockThis( void ) volatile = 0;
+
+ /// Pointer to singly-linked list of mutexes locked by the current thread.
+ static LOKI_THREAD_LOCAL volatile LevelMutexInfo * s_currentMutex;
+
+ /// Level of this mutex.
+ const unsigned int m_level;
+
+ /// How many times this mutex got locked.
+ unsigned int m_count;
+
+ /// Pointer to mutex locked before this one.
+ volatile LevelMutexInfo * m_previous;
+
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class ThrowOnAnyMutexError
+ Implements the ErrorPolicy for LevelMutex and throws an exception for any
+ error condition. Only allows MutexErrors::Success and MutexErrors::NoProblem
+ to get through. Useful for release builds.
+ */
+class ThrowOnAnyMutexError
+{
+public:
+ static MutexErrors::Type CheckError( MutexErrors::Type error,
+ unsigned int level );
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class ThrowOnBadDesignMutexError
+ Implements the ErrorPolicy for LevelMutex and throws an exception if the error
+ indicates the programmer did not levelize the calls to mutexes. Otherwise
+ returns the error result. Useful for release builds.
+ */
+class ThrowOnBadDesignMutexError
+{
+public:
+ static MutexErrors::Type CheckError( MutexErrors::Type error,
+ unsigned int level );
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class AssertAnyMutexError
+ Implements the ErrorPolicy for LevelMutex and asserts for any error condition.
+ Only allows MutexErrors::Success and MutexErrors::NoProblem to get through.
+ Useful for testing mutexes in debug builds.
+ */
+class AssertAnyMutexError
+{
+public:
+ static inline MutexErrors::Type CheckError( MutexErrors::Type error,
+ unsigned int level )
+ {
+ (void)level;
+ assert( ( error == MutexErrors::Success )
+ || ( error == MutexErrors::NoProblem ) );
+ return error;
+ }
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class AssertBadDesignMutexError
+ Implements the ErrorPolicy for LevelMutex and asserts if the error
+ indicates the programmer did not levelize the calls to mutexes. Otherwise
+ returns the error result. Useful for testing mutexes in debug builds.
+ */
+class AssertBadDesignMutexError
+{
+public:
+ static inline MutexErrors::Type CheckError( MutexErrors::Type error,
+ unsigned int level )
+ {
+ (void)level;
+ assert( ( error != MutexErrors::LevelTooHigh )
+ && ( error != MutexErrors::LevelTooLow ) );
+ return error;
+ }
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class JustReturnMutexError
+ Implements the ErrorPolicy for LevelMutex and does nothing no matter how bad
+ the error condition. Only recommended use is for automated unit-testing of
+ mutex policies.
+ */
+class JustReturnMutexError
+{
+public:
+ static inline MutexErrors::Type CheckError( MutexErrors::Type error,
+ unsigned int level )
+ {
+ (void)level;
+ return error;
+ }
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class NoMutexWait
+ Implements the WaitPolicy for LevelMutex. Does nothing at all so it turns
+ all wait loops into spin loops. Useful for low-level mutexes.
+ */
+class NoMutexWait
+{
+public:
+ static inline void Wait( void ) {}
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class MutexSleepWaits
+ Implements the WaitPolicy for LevelMutex. Sleeps for a moment so thread won't
+ consume idle CPU cycles. Useful for high-level mutexes.
+ */
+class MutexSleepWaits
+{
+public:
+ static void Wait( void );
+ static unsigned int sleepTime;
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class SpinLevelMutex
+ Implements a spin-loop to wait for the mutex to unlock. Since this class makes
+ the thread wait in a tight spin-loop, it can cause the thread to remain busy
+ while waiting and thus consume CPU cycles. For that reason, this mutex is best
+ used only for very low-level resources - especially resources which do not
+ require much CPU time to exercise. Rule of thumb: Use this only if all actions
+ on the resource consume a very small number of CPU cycles. Otherwise, use the
+ SleepLevelMutex instead.
+ */
+class SpinLevelMutex
+{
+public:
+
+ /// Constructs a spin-level mutex.
+ explicit SpinLevelMutex( unsigned int level );
+
+ /// Destructs the mutex.
+ virtual ~SpinLevelMutex( void );
+
+ virtual MutexErrors::Type Lock( void ) volatile;
+
+ virtual MutexErrors::Type TryLock( void ) volatile;
+
+ virtual MutexErrors::Type Unlock( void ) volatile;
+
+ inline unsigned int GetLevel( void ) const volatile { return m_level; }
+
+private:
+
+ /// Copy constructor is not implemented.
+ SpinLevelMutex( const SpinLevelMutex & );
+ /// Copy-assignment operator is not implemented.
+ SpinLevelMutex & operator = ( const SpinLevelMutex & );
+
+#if defined( _MSC_VER )
+ #if ( _MSC_VER >= 1300 )
+ /// The actual mutex.
+ CRITICAL_SECTION m_mutex;
+ #else
+ #error "Only Visual Studio versions 7.0 and after supported."
+ #endif
+
+#elif ( __GNUC__ )
+ /// The actual mutex.
+ pthread_mutex_t m_mutex;
+
+#else
+ #error "Check if any mutex libraries are compatible with your compiler."
+#endif
+
+ /// Keep a copy of the mutex level around for error reporting.
+ const unsigned int m_level;
+
+}; // end class SpinLevelMutex
+
+// ----------------------------------------------------------------------------
+
+/** @class SleepLevelMutex
+ Implements a sleeping loop to wait for the mutex to unlock.
+
+ @par Purpose
+ Since this class puts the thread to sleep for short intervals, you can use this
+ class for most of your mutexes. Especially for locking any high level resources
+ where any one operation on the resouce consumes many CPU cycles. The purpose of
+ this mutex is to reduce the number of CPU cycles spent in idle loops. All
+ SleepLevelMutex's should have higher levels than all your SpinLevelMutex's.
+
+ @par Dependence on SpinLevelMutex
+ This utilizes SpinLevelMutex so it does not have to re-implement the DoTryLock
+ and DoUnlock functions the same way. All it really needs is a DoLock function
+ and the amount of time it should sleep if an attempt to lock a function fails.
+ */
+class SleepLevelMutex : public SpinLevelMutex
+{
+public:
+
+ /** Constructs a levelized mutex that puts threads to sleep while they wait
+ for another thread to unlock the mutex.
+ @param level Level of this mutex.
+ */
+ explicit SleepLevelMutex( unsigned int level );
+
+ SleepLevelMutex( unsigned int level, unsigned int sleepTime );
+
+ /// Destructs the mutex.
+ virtual ~SleepLevelMutex( void );
+
+ inline unsigned int GetSleepTime( void ) const volatile { return m_sleepTime; }
+
+ inline void SetSleepTime( unsigned int sleepTime ) volatile
+ {
+ if ( 0 != sleepTime )
+ m_sleepTime = sleepTime;
+ }
+
+#if defined( _MSC_VER )
+ inline bool GetWakable( void ) const volatile { return m_wakable; }
+ inline void SetWakable( bool wakable ) volatile { m_wakable = wakable; }
+#endif
+
+ /** Attempts to lock a mutex, and if it fails, then sleeps for a while
+ before attempting again.
+ */
+ virtual MutexErrors::Type Lock( void ) volatile;
+
+private:
+
+ /// Default constructor is not implemented.
+ SleepLevelMutex( void );
+ /// Copy constructor is not implemented.
+ SleepLevelMutex( const SleepLevelMutex & );
+ /// Copy-assignment operator is not implemented.
+ SleepLevelMutex & operator = ( const SleepLevelMutex & );
+
+#if defined( _MSC_VER )
+ #if ( _MSC_VER >= 1300 )
+ /// True if operating system may wake thread to respond to events.
+ bool m_wakable;
+ #else
+ #error "Only Visual Studio versions 7.0 and after supported."
+ #endif
+#endif
+
+ /// How many milli-seconds to sleep before trying to lock mutex again.
+ unsigned int m_sleepTime;
+
+}; // end class SleepLevelMutex
+
+// ----------------------------------------------------------------------------
+
+/** @class LevelMutex
+ Levelized mutex class prevents deadlocks by requiring programs to lock mutexes in
+ the same order, and unlock them in reverse order. This is accomplished by forcing
+ each mutex to have a level and forcing code to lock mutexes with higher levels
+ before locking mutexes at lower levels. If you want to lock several mutexes, they
+ must be locked in decreasing order by level, or if they are all of the same level,
+ then locked by LevelMutex::MultiLock.
+
+ @par Features
+ - Immune: Very unlikely to deadlock since all mutexes are locked in the same
+ order and unlocked in reverse order.
+ - Scalable: Can handle any number of mutexes.
+ - Efficient: Many operations occur in constant time, and most operations require
+ no more than O(m) steps.
+ - Exception safe: All operations provide strong safety or don't throw.
+ - Extendable: Can work with existing mutexes through policy-based design.
+ - Easily Extended: Derived classes only need to implement 5 functions and a mutex
+ to get all the features of this class.
+ - Re-Entrant: Allows for re-entrancy even if mutexes in policy classes don't.
+ - Cost-Free: No resource allocations occur in LevelMutex - although user-defined
+ policy classes may allocate resources.
+ - Compact: Each LevelMutex object is small.
+ - Portable: As long as your compiler and libraries can meet the requirements.
+ - Robust: Maintains data integrity even if exceptions occur in policy classes.
+ - Affording: Several functions provide information about a mutex which allows
+ client code to easily choose correct actions.
+
+ @par Requirements
+ - Your compiler must allow for thread-specific data.
+ - You must have a threading or mutex library.
+
+ @par Policy-Based Design
+ This class hosts 3 policies and a default level. The policy-based design allows
+ users to write their own policies to extend the behaviors of LevelMutex. The
+ paragraphs below say how to design a class for each policy.
+ - MutexPolicy The mutex policy class.
+ - defaultLevel A level for existing client code that calls a default constructor.
+ - ErrorPolicy How the mutex should handle error conditions.
+ - WaitPolicy Whether a thread should wait, and how long in some internal loops.
+
+ @par MutexPolicy
+ A policy class that wraps a low-level mutex. Loki provides two policy classes
+ for the actual mutex (SpinLevelMutex and SleepLevelMutex), both of which wrap
+ either pthreads or the Windows CRITICAL_SECTION. If you want to use a mutex
+ mechanism besides one of those, then all you have to do is provide a class
+ which wraps the mutex and implements these functions.
+ explicit SpinLevelMutex( unsigned int level );
+ virtual ~SpinLevelMutex( void );
+ virtual MutexErrors::Type Lock( void ) volatile;
+ virtual MutexErrors::Type TryLock( void ) volatile;
+ virtual MutexErrors::Type Unlock( void ) volatile;
+ Indeed, since the base class does most of the work, and provides all the interace
+ and functionality to client classes, a derived class has very few requirements.
+ It only needs to implement a single constructor, the destructor, some virtual
+ functions, and whatever data members it requires. You don't actually need to
+ declare those functions as virtual if the policy class is not a base or child
+ class. In the parlance of design patterns, LevelMutex is a Template, and the
+ MutexPolicy is a Strategy.
+
+ @par DefaultLevel
+ The template class requires a default level to use inside the default constructor.
+ Some existing code calls instantiates mutexes with a default constructor, so the
+ mutex must know what level to use there. Please do not use zero or UnlockedLevel
+ as the default level.
+
+ @par ErrorPolicy
+ This policy specifies how to handle error conditions. The mutexes can return
+ errors, assert, or throw exceptions. I recommend that debug code use asserts,
+ release code use exceptions, and unit-testing code just return errors. The
+ error policy class only needs to implement one function:
+ static MutexErrors::Type CheckError( MutexErrors::Type error, unsigned int level );
+
+ @par WaitPolicy
+ This states whether the mutex should wait within some tight internal loops,
+ how the waiting is done, and for how long. A wait policy class could sleep,
+ do nothing, check if other objects need attention, or check if the program
+ received events or notices from the operating system. It only needs to
+ implement one function:
+ static void Wait( void );
+
+ @par Per-Function Usage
+ If you implement a function with a static local mutex, then you have to insure
+ the function is not called from a lower level via call-backs, virtual functions in
+ interface classes. If the function does get called from a lower level, you are
+ setting up a potential deadlock. LevelMutex will detect that by checking the
+ current level and the local mutex's level, so it will refuse to lock the local mutex.
+
+ @par Per-Object Usage
+ If you use a mutex as a data member of an object to protect that object, then I
+ recommend specifying which functions are volatile and which are not, and then only
+ use the mutex within the volatile functions. You may also want to provide accessor
+ functions so that client code can lock and unlock the mutex either to allow for
+ calling multiple operations without having to lock and unlock before and after each
+ operation, or so they can lock it along with several other objects at the same
+ level.
+
+ @par Per-Class Usage
+ If you make a static data member within a class, you can use that to lock any
+ resources shared by those objects, or to require threads to act on only one object
+ at a time. You may also want to provide static accessor functions so that client
+ code can lock several other resources at the same level.
+ */
+
+template
+<
+ class MutexPolicy,
+ unsigned int DefaultLevel,
+ class ErrorPolicy = ::Loki::ThrowOnBadDesignMutexError,
+ class WaitPolicy = ::Loki::NoMutexWait
+>
+class LevelMutex : public LevelMutexInfo
+{
+public:
+
+ typedef ErrorPolicy EP;
+ typedef WaitPolicy WP;
+ typedef MutexPolicy MP;
+
+ /** This constructor allows callers to replace the default level with another
+ value. It also acts as the default constructor for existing code which uses
+ default construction for mutexes. This is the only time the DefaultLevel
+ template parameter gets used.
+ */
+ explicit LevelMutex( unsigned int level = DefaultLevel ) :
+ LevelMutexInfo( level ),
+ m_mutex( level )
+ {
+ assert( IsValid() );
+ }
+
+ /// The destructor.
+ ~LevelMutex( void )
+ {
+ assert( IsValid() );
+ }
+
+ /** These functions allow callers to access the mutex in case they need to
+ modify specific values in the MutexPolicy (e.g. - sleep time, functors to
+ call as tasks, etc...) There is one function for every combination of
+ const and volatile qualifiers so callers get a reference to a MutexPolicy
+ with the proper qualifiers.
+ */
+ inline const volatile MutexPolicy & GetMutexPolicy( void ) const volatile { return m_mutex; }
+ inline volatile MutexPolicy & GetMutexPolicy( void ) volatile { return m_mutex; }
+ inline const MutexPolicy & GetMutexPolicy( void ) const { return m_mutex; }
+ inline MutexPolicy & GetMutexPolicy( void ) { return m_mutex; }
+
+ virtual MutexErrors::Type TryLock( void ) volatile
+ {
+ assert( IsValid() );
+ LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; )
+
+ MutexErrors::Type result = LevelMutexInfo::PreLockCheck( true );
+ if ( MutexErrors::Success == result )
+ return MutexErrors::Success;
+ else if ( MutexErrors::AlreadyLocked == result )
+ return result;
+ else if ( MutexErrors::NoProblem != result )
+ return EP::CheckError( result, GetLevel() );
+
+ assert( 0 == LevelMutexInfo::GetLockCount() );
+ result = m_mutex.TryLock();
+ if ( MutexErrors::Success != result )
+ return EP::CheckError( result, GetLevel() );
+ LevelMutexInfo::PostLock();
+
+ return MutexErrors::Success;
+ }
+
+ virtual MutexErrors::Type Lock( void ) volatile
+ {
+ assert( IsValid() );
+ LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; )
+
+ MutexErrors::Type result = LevelMutexInfo::PreLockCheck( false );
+ if ( MutexErrors::Success == result )
+ return MutexErrors::Success;
+ else if ( MutexErrors::NoProblem != result )
+ return EP::CheckError( result, GetLevel() );
+
+ assert( !LevelMutexInfo::IsLockedByCurrentThread() );
+ result = m_mutex.Lock();
+ if ( MutexErrors::Success != result )
+ return EP::CheckError( result, GetLevel() );
+ PostLock();
+
+ return MutexErrors::Success;
+ }
+
+ virtual MutexErrors::Type Lock( unsigned int milliSeconds ) volatile
+ {
+ assert( IsValid() );
+ LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; )
+
+ MutexErrors::Type result = LevelMutexInfo::PreLockCheck( false );
+ if ( MutexErrors::Success == result )
+ return MutexErrors::Success;
+ else if ( MutexErrors::NoProblem != result )
+ return EP::CheckError( result, GetLevel() );
+
+ assert( !LevelMutexInfo::IsLockedByCurrentThread() );
+ clock_t timeOut = clock() + milliSeconds;
+ while ( clock() < timeOut )
+ {
+ WP::Wait();
+ result = m_mutex.TryLock();
+ switch ( result )
+ {
+ case MutexErrors::Success:
+ {
+ PostLock();
+ return MutexErrors::Success;
+ }
+ case MutexErrors::AlreadyLocked:
+ return MutexErrors::AlreadyLocked;
+ case MutexErrors::TryFailed:
+ break;
+ default:
+ return EP::CheckError( result, GetLevel() );
+ }
+ }
+
+ return MutexErrors::TimedOut;
+ }
+
+ virtual MutexErrors::Type Unlock( void ) volatile
+ {
+ assert( IsValid() );
+ LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; )
+
+ MutexErrors::Type result = LevelMutexInfo::PreUnlockCheck();
+ if ( MutexErrors::Success == result )
+ return MutexErrors::Success;
+ else if ( MutexErrors::NoProblem != result )
+ return EP::CheckError( result, GetLevel() );
+
+ LevelMutexInfo::PreUnlock();
+ result = MutexErrors::OtherError;
+ try
+ {
+ result = m_mutex.Unlock();
+ if ( MutexErrors::Success != result )
+ PostLock();
+ }
+ catch ( ... )
+ {
+ PostLock();
+ result = MutexErrors::ExceptionThrown;
+ }
+
+ return result;
+ }
+
+private:
+
+ /// Copy constructor is not implemented since mutexes don't get copied.
+ LevelMutex( const LevelMutex & );
+ /// Copy-assignment operator is not implemented since mutexes don't get copied.
+ LevelMutex & operator = ( const LevelMutex & );
+
+ virtual MutexErrors::Type DoErrorCheck( MutexErrors::Type result ) const volatile
+ {
+ return EP::CheckError( result, GetLevel() );
+ }
+
+ /** Called only by MultiLock to lock each particular mutex within a container.
+ This does not do pre-lock error checking since MultiLock does that. Since
+ this skips the error checking, that means that callers of LevelMutex should
+ not call this function directly, and so this will not be publicly available.
+ @return Error status indicating success or reason for failure.
+ */
+ virtual MutexErrors::Type LockThis( void ) volatile
+ {
+ assert( IsValid() );
+ LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; )
+ assert( this != LevelMutexInfo::GetCurrentMutex() );
+
+ const MutexErrors::Type result = m_mutex.Lock();
+ if ( MutexErrors::Success != result )
+ return result;
+ PostLock();
+
+ return MutexErrors::Success;
+ }
+
+ /** Called only by MultiLock to lock each particular mutex within a container.
+ This does not do pre-lock error checking since MultiLock does that. Since
+ this skips the error checking, callers of LevelMutex should not call this
+ function directly, and so this will not be publicly available.
+ @param milliSeconds How much time to wait before giving up on locking a mutex.
+ @return Error status indicating success or reason for failure.
+ */
+ virtual MutexErrors::Type LockThis( unsigned int milliSeconds ) volatile
+ {
+ assert( IsValid() );
+ LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; )
+
+ clock_t timeOut = clock() + milliSeconds;
+ while ( clock() < timeOut )
+ {
+ WP::Wait();
+ const bool locked = ( MutexErrors::Success == m_mutex.TryLock() );
+ if ( locked )
+ {
+ PostLock();
+ return MutexErrors::Success;
+ }
+ }
+
+ return MutexErrors::TimedOut;
+ }
+
+ /** Called only by MultiUnlock to unlock each mutex within a container.
+ This does not do pre-unlock error checking since MultiLock does that. Since
+ this skips the error checking, callers of LevelMutex should not call this
+ function directly, and so this will not be publicly available.
+ @return Error status indicating success or reason for failure.
+ */
+ virtual MutexErrors::Type UnlockThis( void ) volatile
+ {
+ assert( IsValid() );
+ assert( NULL != LevelMutexInfo::GetCurrentMutex() );
+ LOKI_MUTEX_DEBUG_CODE( Checker checker( this ); (void)checker; )
+
+ if ( 1 < LevelMutexInfo::GetLockCount() )
+ {
+ LevelMutexInfo::DecrementCount();
+ return MutexErrors::Success;
+ }
+
+ LevelMutexInfo::PreUnlock();
+ MutexErrors::Type result = m_mutex.Unlock();
+
+ return result;
+ }
+
+ /// An instance of an unleveled mutex wrapped to match LevelMutex's needs.
+ MutexPolicy m_mutex;
+
+}; // end class LevelMutex
+
+// ----------------------------------------------------------------------------
+
+/** Returns level of most recently locked mutex by this thread, or UnlockedLevel
+ if no mutexes are locked. Runs in constant time, and never throws exceptions.
+ */
+unsigned int GetCurrentThreadsLevel( void );
+
+/** Returns count of how mutexes the current thread locked. Requires O(m)
+ actions where m is the number of mutexes in the thread. Never throws exceptions.
+ */
+unsigned int CountMutexesInCurrentThread( void );
+
+/** Returns count of how mutexes the current thread locked. The lock count
+ exceeds the number of mutexes locked by current thread if any mutex got locked
+ more than once. Requires O(m) actions where m is the number of mutexes in the
+ thread. Never throws exceptions.
+ */
+unsigned int CountLocksInCurrentThread( void );
+
+/** Returns count of mutexes locked by current thread which have the same level
+ as GetCurrentThreadsLevel. Requires O(m) actions where m is the number of
+ mutexes in the thread at current level. Never throws exceptions.
+ */
+unsigned int CountMutexesAtCurrentLevel( void );
+
+/** Determines if container of mutexes matches the recently locked mutexes.
+ If they do match, it returns success, otherwise an error condition.
+ */
+MutexErrors::Type DoMutexesMatchContainer( const LevelMutexInfo::MutexContainer & mutexes );
+
+// ----------------------------------------------------------------------------
+
+/** @class MutexException
+ Exception class used to throw error statuses about LevelMutex's up to code that
+ can respond to mutex problems. This class exists because it conveys more info
+ about the error condition than just ::std::exception.
+ */
+class MutexException : public ::std::exception
+{
+public:
+
+ /** Constructs an exception which stores information about a mutex and the
+ reason an attempt to use a mutex failed.
+ */
+ MutexException( const char * message, unsigned int level, MutexErrors::Type reason );
+
+ /// Copy constructor performs a member-by-member copy of an exception.
+ MutexException( const MutexException & that ) throw ();
+
+ /// Copy-assignment operator performs a member-by-member copy of an exception.
+ MutexException & operator = ( const MutexException & that ) throw ();
+
+ /// Destroys the exception.
+ virtual ~MutexException( void ) throw();
+
+ /// Returns a simple message about which operation failed.
+ virtual const char * what( void ) const throw();
+
+ /// Returns level of mutex(es) used when problem occurred.
+ unsigned int GetLevel( void ) const { return m_level; }
+
+ /// Returns an error status for why operation failed.
+ MutexErrors::Type GetReason( void ) const { return m_reason; }
+
+private:
+
+ /// Default constructor is not implemented.
+ MutexException( void ) throw ();
+
+ /// Simple message about operation that failed.
+ const char * m_message;
+ /// Level of mutex(es) used when problem occurred.
+ unsigned int m_level;
+ /// Error status for why operation failed.
+ MutexErrors::Type m_reason;
+
+}; // end class MutexException
+
+// ----------------------------------------------------------------------------
+
+/** @class MutexLocker
+ You can place an instance of this as a local variable inside a function to lock
+ a single mutex. It will lock the mutex if no error occurs, or throw if one
+ does happen. When the function ends, the destructor will determine if it needs
+ to unlock the mutex. This RAII technique insures the mutex gets unlocked even
+ when exceptions occur.
+ */
+class MutexLocker
+{
+public:
+
+ /** Creates an object to lock an unlock a mutex for a function. This
+ will throw if an attempt to lock the mutex fails.
+ @param mutex Reference to the mutex.
+ @param lock True if function wants to lock the mutex as this gets
+ constructed.
+ */
+ explicit MutexLocker( volatile LevelMutexInfo & mutex, bool lock = true );
+
+ /** Creates an object to lock an unlock a mutex for a function. This waits
+ a specified amount of time for another thread to unlock the mutex if it is
+ locked. This will throw if an attempt to lock the mutex fails.
+ @param mutex Reference to the mutex.
+ @param milliSeconds Amount of time to wait for another thread to unlock
+ the mutex.
+ @param lock True if function wants to lock the mutex as this gets
+ constructed.
+ */
+ MutexLocker( volatile LevelMutexInfo & mutex, unsigned int milliSeconds,
+ bool lock = true );
+
+ /// Destructs the locker, and determines if it needs to unlock the mutex.
+ ~MutexLocker( void );
+
+ /** You can call this to lock (or relock) a mutex. In theory, you can lock
+ and unlock a mutex several times within a function in order to give other
+ threads access to a resource while this function does not need it.
+ @return True if mutex is locked by this, else false if not locked.
+ */
+ bool Lock( void );
+
+ /** You can call this to unlock a mutex before the destructor does it.
+ By unlocking the mutexes before returning, the function can do other
+ operations without making other threads wait too long.
+ @return True if unlocked by this, else false if not unlocked by this.
+ (Which is not the same as whether the mutex itself is locked or not by
+ another thread.)
+ */
+ bool Unlock( void );
+
+ /// Returns true if the mutex is locked by this object.
+ inline bool IsLocked( void ) const { return m_locked; }
+
+ /// Provides access to mutex controlled by this.
+ const volatile LevelMutexInfo & GetMutex( void ) const { return m_mutex; }
+
+private:
+
+ /// Default constructor is not implemented.
+ MutexLocker( void );
+ /// Copy constructor is not implemented.
+ MutexLocker( const MutexLocker & );
+ /// Copy-assignment operator is not implemented.
+ MutexLocker & operator = ( const MutexLocker & );
+
+ /// True if mutex got locked.
+ bool m_locked;
+
+ /// Reference to mutex.
+ volatile LevelMutexInfo & m_mutex;
+};
+
+// ----------------------------------------------------------------------------
+
+/** @class MultiMutexLocker
+ You can place an instance of this as a local variable inside a function to lock
+ a collection of mutexes. It locks them if no error occurs, or throws an
+ exception if one does happen. When the function ends, the destructor determines
+ if it needs to unlock the mutexes. This RAII technique insures the mutexes get
+ unlocked even when exceptions occur. You will also have to construct a
+ MutexContainer as a local object within the same function.
+ */
+class MultiMutexLocker
+{
+public:
+
+ /** Creates an object to lock and unlock a collection of mutexes for a function.
+ This will throw if an attempt to lock any mutex fails. If an exception occurs,
+ it unlocks mutexes it previously locked.
+ @param mutex Reference to a collection of mutexes.
+ @param lock True if function wants to lock the mutex as this gets
+ constructed.
+ */
+ explicit MultiMutexLocker( LevelMutexInfo::MutexContainer & mutexes,
+ bool lock = true );
+
+ /** Creates an object to lock and unlock a collection of mutexes for a function.
+ This waits a specified amount of time for other threads to unlock each mutex
+ that is locked. This will throw if an attempt to lock any mutex fails. If an
+ exception occurs, it unlocks mutexes it previously locked.
+ @param mutexes Reference to a collection of mutexes.
+ @param milliSeconds Amount of time to wait for another thread to unlock
+ the mutex.
+ @param lock True if function wants to lock the mutexes as this gets
+ constructed.
+ */
+ MultiMutexLocker( LevelMutexInfo::MutexContainer & mutexes,
+ unsigned int milliSeconds, bool lock = true );
+
+ /// Destructs the locker, and determines if it needs to unlock the mutexes.
+ ~MultiMutexLocker( void );
+
+ /** You can call this to lock (or relock) the mutexes. In theory, you can lock
+ and unlock mutexes several times within a function in order to give other
+ threads access to resources while this function does not need them.
+ @return True if mutex is locked by this, else false if not locked.
+ */
+ bool Lock( void );
+
+ /** You can call this to unlock the mutexes before the destructor does it.
+ By unlocking the mutexes before returning, the function can do other
+ operations without making other threads wait too long.
+ @return True if unlocked by this, else false if not unlocked by this.
+ (Which is not the same as whether the mutex itself is locked or not by
+ another thread.)
+ */
+ bool Unlock( void );
+
+ /// Returns true if the mutexes are locked by this object.
+ inline bool IsLocked( void ) const { return m_locked; }
+
+ /// Provides access to the collection of mutexes controlled by this.
+ const LevelMutexInfo::MutexContainer & GetMutexes( void ) const { return m_mutexes; }
+
+private:
+
+ /// Default constructor is not implemented.
+ MultiMutexLocker( void );
+ /// Copy constructor is not implemented.
+ MultiMutexLocker( const MultiMutexLocker & );
+ /// Copy-assignment operator is not implemented.
+ MultiMutexLocker & operator = ( const MultiMutexLocker & );
+
+ /// True if mutexes got locked.
+ bool m_locked;
+
+ /// Reference to external container of mutexes;
+ LevelMutexInfo::MutexContainer & m_mutexes;
+};
+
+// ----------------------------------------------------------------------------
+
+} // end namespace Loki
+
+#endif // end file guardian
diff --git a/shared/loki/LockingPtr.h b/shared/loki/LockingPtr.h
new file mode 100644
index 00000000..a50f5d6d
--- /dev/null
+++ b/shared/loki/LockingPtr.h
@@ -0,0 +1,110 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code is from the article:
+// "Generic<Programming>: volatile — Multithreaded Programmer’s Best Friend
+// Volatile-Correctness or How to Have Your Compiler Detect Race Conditions
+// for You" by Alexandrescu, Andrei.
+// Published in the February 2001 issue of the C/C++ Users Journal.
+// http://www.cuj.com/documents/s=7998/cujcexp1902alexandr/
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+// Prepared for Loki library by Richard Sposato
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_LOCKING_PTR_INC_
+#define LOKI_LOCKING_PTR_INC_
+
+// $Id: LockingPtr.h 840 2008-03-19 19:44:38Z rich_sposato $
+
+
+#include <loki/ConstPolicy.h>
+#include <loki/Threads.h>
+
+
+namespace Loki
+{
+ /** @class LockingPtr
+ Locks a volatile object and casts away volatility so that the object
+ can be safely used in a single-threaded region of code.
+ Original version of LockingPtr had only one template - for the shared
+ object, but not the mutex type. This version allows users to specify a
+ the mutex type as a LockingPolicy class. The only requirements for a
+ LockingPolicy class are to provide Lock and Unlock methods.
+ */
+ template < typename SharedObject, typename LockingPolicy = LOKI_DEFAULT_MUTEX,
+ template<class> class ConstPolicy = LOKI_DEFAULT_CONSTNESS >
+ class LockingPtr
+ {
+ public:
+
+ typedef typename ConstPolicy<SharedObject>::Type ConstOrNotType;
+
+ /** Constructor locks mutex associated with an object.
+ @param object Reference to object.
+ @param mutex Mutex used to control thread access to object.
+ */
+ LockingPtr( volatile ConstOrNotType & object, LockingPolicy & mutex )
+ : pObject_( const_cast< SharedObject * >( &object ) ),
+ pMutex_( &mutex )
+ {
+ mutex.Lock();
+ }
+
+ typedef typename std::pair<volatile ConstOrNotType *, LockingPolicy *> Pair;
+
+ /** Constructor locks mutex associated with an object.
+ @param lockpair a std::pair of pointers to the object and the mutex
+ */
+ LockingPtr( Pair lockpair )
+ : pObject_( const_cast< SharedObject * >( lockpair.first ) ),
+ pMutex_( lockpair.second )
+ {
+ lockpair.second->Lock();
+ }
+
+ /// Destructor unlocks the mutex.
+ ~LockingPtr()
+ {
+ pMutex_->Unlock();
+ }
+
+ /// Star-operator dereferences pointer.
+ ConstOrNotType & operator * ()
+ {
+ return *pObject_;
+ }
+
+ /// Point-operator returns pointer to object.
+ ConstOrNotType * operator -> ()
+ {
+ return pObject_;
+ }
+
+ private:
+
+ /// Default constructor is not implemented.
+ LockingPtr();
+
+ /// Copy-constructor is not implemented.
+ LockingPtr( const LockingPtr & );
+
+ /// Copy-assignment-operator is not implemented.
+ LockingPtr & operator = ( const LockingPtr & );
+
+ /// Pointer to the shared object.
+ ConstOrNotType * pObject_;
+
+ /// Pointer to the mutex.
+ LockingPolicy * pMutex_;
+
+ }; // end class LockingPtr
+
+} // namespace Loki
+
+#endif // end file guardian
+
diff --git a/shared/loki/LokiExport.h b/shared/loki/LokiExport.h
new file mode 100644
index 00000000..625449f2
--- /dev/null
+++ b/shared/loki/LokiExport.h
@@ -0,0 +1,69 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 by Peter Kümmel
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_LOKIEXPORT_INC_
+#define LOKI_LOKIEXPORT_INC_
+
+// $Id: LokiExport.h 748 2006-10-17 19:49:08Z syntheticpp $
+
+
+#ifdef __GNUC__
+
+#ifdef _HAVE_GCC_VISIBILITY
+#define LOKI_EXPORT_SPEC __attribute__ ((visibility("default")))
+#define LOKI_IMPORT_SPEC
+#else
+#define LOKI_EXPORT_SPEC
+#define LOKI_IMPORT_SPEC
+#endif
+
+#else
+
+#ifdef _WIN32
+#define LOKI_EXPORT_SPEC __declspec(dllexport)
+#define LOKI_IMPORT_SPEC __declspec(dllimport)
+#else
+#define LOKI_EXPORT_SPEC
+#define LOKI_IMPORT_SPEC
+#endif
+
+#endif
+
+
+#if (defined(LOKI_MAKE_DLL) && defined(LOKI_DLL)) || \
+ (defined(LOKI_MAKE_DLL) && defined(LOKI_STATIC)) || \
+ (defined(LOKI_DLL) && defined(LOKI_STATIC))
+#error export macro error: you could not build AND use the library
+#endif
+
+#ifdef LOKI_MAKE_DLL
+#define LOKI_EXPORT LOKI_EXPORT_SPEC
+#endif
+
+#ifdef LOKI_DLL
+#define LOKI_EXPORT LOKI_IMPORT_SPEC
+#endif
+
+#ifdef LOKI_STATIC
+#define LOKI_EXPORT
+#endif
+
+#if !defined(LOKI_EXPORT) && !defined(EXPLICIT_EXPORT)
+#define LOKI_EXPORT
+#endif
+
+#ifndef LOKI_EXPORT
+#error export macro error: LOKI_EXPORT was not defined, disable EXPLICIT_EXPORT or define a export specification
+#endif
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/LokiTypeInfo.h b/shared/loki/LokiTypeInfo.h
new file mode 100644
index 00000000..715dab1a
--- /dev/null
+++ b/shared/loki/LokiTypeInfo.h
@@ -0,0 +1,103 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_LOKITYPEINFO_INC_
+#define LOKI_LOKITYPEINFO_INC_
+
+// $Id: LokiTypeInfo.h 748 2006-10-17 19:49:08Z syntheticpp $
+
+
+#include <typeinfo>
+#include <cassert>
+#include "Typelist.h"
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class TypeInfo
+// Purpose: offer a first-class, comparable wrapper over std::type_info
+////////////////////////////////////////////////////////////////////////////////
+
+ class TypeInfo
+ {
+ public:
+ // Constructors
+ TypeInfo(); // needed for containers
+ TypeInfo(const std::type_info&); // non-explicit
+
+ // Access for the wrapped std::type_info
+ const std::type_info& Get() const;
+ // Compatibility functions
+ bool before(const TypeInfo& rhs) const;
+ const char* name() const;
+
+ private:
+ const std::type_info* pInfo_;
+ };
+
+// Implementation
+
+ inline TypeInfo::TypeInfo()
+ {
+ class Nil {};
+ pInfo_ = &typeid(Nil);
+ assert(pInfo_);
+ }
+
+ inline TypeInfo::TypeInfo(const std::type_info& ti)
+ : pInfo_(&ti)
+ { assert(pInfo_); }
+
+ inline bool TypeInfo::before(const TypeInfo& rhs) const
+ {
+ assert(pInfo_);
+ // type_info::before return type is int in some VC libraries
+ return pInfo_->before(*rhs.pInfo_) != 0;
+ }
+
+ inline const std::type_info& TypeInfo::Get() const
+ {
+ assert(pInfo_);
+ return *pInfo_;
+ }
+
+ inline const char* TypeInfo::name() const
+ {
+ assert(pInfo_);
+ return pInfo_->name();
+ }
+
+// Comparison operators
+
+ inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
+ // type_info::operator== return type is int in some VC libraries
+ { return (lhs.Get() == rhs.Get()) != 0; }
+
+ inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
+ { return lhs.before(rhs); }
+
+ inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs)
+ { return !(lhs == rhs); }
+
+ inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs)
+ { return rhs < lhs; }
+
+ inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs)
+ { return !(lhs > rhs); }
+
+ inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs)
+ { return !(lhs < rhs); }
+}
+
+#endif // end file guardian
diff --git a/shared/loki/MultiMethods.h b/shared/loki/MultiMethods.h
new file mode 100644
index 00000000..d095cfae
--- /dev/null
+++ b/shared/loki/MultiMethods.h
@@ -0,0 +1,415 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_MULTIMETHODS_INC_
+#define LOKI_MULTIMETHODS_INC_
+
+// $Id: MultiMethods.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+#include "Typelist.h"
+#include "LokiTypeInfo.h"
+#include "Functor.h"
+#include "AssocVector.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// IMPORTANT NOTE:
+// The double dispatchers implemented below differ from the excerpts shown in
+// the book - they are simpler while respecting the same interface.
+////////////////////////////////////////////////////////////////////////////////
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class template InvocationTraits (helper)
+// Helps implementing optional symmetry
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ template <class SomeLhs, class SomeRhs,
+ class Executor, typename ResultType>
+ struct InvocationTraits
+ {
+ static ResultType
+ DoDispatch(SomeLhs& lhs, SomeRhs& rhs,
+ Executor& exec, Int2Type<false>)
+ {
+ return exec.Fire(lhs, rhs);
+ }
+ static ResultType
+ DoDispatch(SomeLhs& lhs, SomeRhs& rhs,
+ Executor& exec, Int2Type<true>)
+ {
+ return exec.Fire(rhs, lhs);
+ }
+ };
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// class template StaticDispatcher
+// Implements an automatic static double dispatcher based on two typelists
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ class Executor,
+ class BaseLhs,
+ class TypesLhs,
+ bool symmetric = true,
+ class BaseRhs = BaseLhs,
+ class TypesRhs = TypesLhs,
+ typename ResultType = void
+ >
+ class StaticDispatcher
+ {
+ template <class SomeLhs>
+ static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
+ Executor exec, NullType)
+ { return exec.OnError(lhs, rhs); }
+
+ template <class Head, class Tail, class SomeLhs>
+ static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
+ Executor exec, Typelist<Head, Tail>)
+ {
+ if (Head* p2 = dynamic_cast<Head*>(&rhs))
+ {
+ Int2Type<(symmetric &&
+ int(TL::IndexOf<TypesRhs, Head>::value) <
+ int(TL::IndexOf<TypesLhs, SomeLhs>::value))> i2t;
+
+ typedef Private::InvocationTraits<
+ SomeLhs, Head, Executor, ResultType> CallTraits;
+
+ return CallTraits::DoDispatch(lhs, *p2, exec, i2t);
+ }
+ return DispatchRhs(lhs, rhs, exec, Tail());
+ }
+
+ static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,
+ Executor exec, NullType)
+ { return exec.OnError(lhs, rhs); }
+
+ template <class Head, class Tail>
+ static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,
+ Executor exec, Typelist<Head, Tail>)
+ {
+ if (Head* p1 = dynamic_cast<Head*>(&lhs))
+ {
+ return DispatchRhs(*p1, rhs, exec, TypesRhs());
+ }
+ return DispatchLhs(lhs, rhs, exec, Tail());
+ }
+
+ public:
+ static ResultType Go(BaseLhs& lhs, BaseRhs& rhs,
+ Executor exec)
+ { return DispatchLhs(lhs, rhs, exec, TypesLhs()); }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template BasicDispatcher
+// Implements a logarithmic double dispatcher for functors (or functions)
+// Doesn't offer automated casts or symmetry
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ class BaseLhs,
+ class BaseRhs = BaseLhs,
+ typename ResultType = void,
+ typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)
+ >
+ class BasicDispatcher
+ {
+ typedef std::pair<TypeInfo,TypeInfo> KeyType;
+ typedef CallbackType MappedType;
+ typedef AssocVector<KeyType, MappedType> MapType;
+ MapType callbackMap_;
+
+ void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun);
+ bool DoRemove(TypeInfo lhs, TypeInfo rhs);
+
+ public:
+ template <class SomeLhs, class SomeRhs>
+ void Add(CallbackType fun)
+ {
+ DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun);
+ }
+
+ template <class SomeLhs, class SomeRhs>
+ bool Remove()
+ {
+ return DoRemove(typeid(SomeLhs), typeid(SomeRhs));
+ }
+
+ ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
+ };
+
+ // Non-inline to reduce compile time overhead...
+ template <class BaseLhs, class BaseRhs,
+ typename ResultType, typename CallbackType>
+ void BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
+ ::DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun)
+ {
+ callbackMap_[KeyType(lhs, rhs)] = fun;
+ }
+
+ template <class BaseLhs, class BaseRhs,
+ typename ResultType, typename CallbackType>
+ bool BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
+ ::DoRemove(TypeInfo lhs, TypeInfo rhs)
+ {
+ return callbackMap_.erase(KeyType(lhs, rhs)) == 1;
+ }
+
+ template <class BaseLhs, class BaseRhs,
+ typename ResultType, typename CallbackType>
+ ResultType BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
+ ::Go(BaseLhs& lhs, BaseRhs& rhs)
+ {
+ typename MapType::key_type k(typeid(lhs),typeid(rhs));
+ typename MapType::iterator i = callbackMap_.find(k);
+ if (i == callbackMap_.end())
+ {
+ throw std::runtime_error("Function not found");
+ }
+ return (i->second)(lhs, rhs);
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// class template StaticCaster
+// Implementation of the CastingPolicy used by FunctorDispatcher
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class To, class From>
+ struct StaticCaster
+ {
+ static To& Cast(From& obj)
+ {
+ return static_cast<To&>(obj);
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template DynamicCaster
+// Implementation of the CastingPolicy used by FunctorDispatcher
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class To, class From>
+ struct DynamicCaster
+ {
+ static To& Cast(From& obj)
+ {
+ return dynamic_cast<To&>(obj);
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Private::FnDispatcherHelper
+// Implements trampolines and argument swapping used by FnDispatcher
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ template <class BaseLhs, class BaseRhs,
+ class SomeLhs, class SomeRhs,
+ typename ResultType,
+ class CastLhs, class CastRhs,
+ ResultType (*Callback)(SomeLhs&, SomeRhs&)>
+ struct FnDispatcherHelper
+ {
+ static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
+ {
+ return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
+ }
+ static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
+ {
+ return Trampoline(lhs, rhs);
+ }
+ };
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FnDispatcher
+// Implements an automatic logarithmic double dispatcher for functions
+// Features automated conversions
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class BaseLhs, class BaseRhs = BaseLhs,
+ typename ResultType = void,
+ template <class, class> class CastingPolicy = DynamicCaster,
+ template <class, class, class, class>
+ class DispatcherBackend = BasicDispatcher>
+ class FnDispatcher
+ {
+ DispatcherBackend<BaseLhs, BaseRhs, ResultType,
+ ResultType (*)(BaseLhs&, BaseRhs&)> backEnd_;
+
+ public:
+ template <class SomeLhs, class SomeRhs>
+ void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&))
+ {
+ return backEnd_.template Add<SomeLhs, SomeRhs>(pFun);
+ }
+
+ template <class SomeLhs, class SomeRhs,
+ ResultType (*callback)(SomeLhs&, SomeRhs&)>
+ void Add()
+ {
+ typedef Private::FnDispatcherHelper<
+ BaseLhs, BaseRhs,
+ SomeLhs, SomeRhs,
+ ResultType,
+ CastingPolicy<SomeLhs,BaseLhs>,
+ CastingPolicy<SomeRhs,BaseRhs>,
+ callback> Local;
+
+ Add<SomeLhs, SomeRhs>(&Local::Trampoline);
+ }
+
+ template <class SomeLhs, class SomeRhs,
+ ResultType (*callback)(SomeLhs&, SomeRhs&),
+ bool symmetric>
+ void Add(bool = true) // [gcc] dummy bool
+ {
+ typedef Private::FnDispatcherHelper<
+ BaseLhs, BaseRhs,
+ SomeLhs, SomeRhs,
+ ResultType,
+ CastingPolicy<SomeLhs,BaseLhs>,
+ CastingPolicy<SomeRhs,BaseRhs>,
+ callback> Local;
+
+ Add<SomeLhs, SomeRhs>(&Local::Trampoline);
+ if (symmetric)
+ {
+ Add<SomeRhs, SomeLhs>(&Local::TrampolineR);
+ }
+ }
+
+ template <class SomeLhs, class SomeRhs>
+ void Remove()
+ {
+ backEnd_.template Remove<SomeLhs, SomeRhs>();
+ }
+
+ ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
+ {
+ return backEnd_.Go(lhs, rhs);
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorDispatcherAdaptor
+// permits use of FunctorDispatcher under gcc.2.95.2/3
+///////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ template <class BaseLhs, class BaseRhs,
+ class SomeLhs, class SomeRhs,
+ typename ResultType,
+ class CastLhs, class CastRhs,
+ class Fun, bool SwapArgs>
+ class FunctorDispatcherHelper
+ {
+ Fun fun_;
+ ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>)
+ {
+ return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
+ }
+ ResultType Fire(BaseLhs& rhs, BaseRhs& lhs,Int2Type<true>)
+ {
+ return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
+ }
+ public:
+ FunctorDispatcherHelper(const Fun& fun) : fun_(fun) {}
+
+ ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
+ {
+ return Fire(lhs,rhs,Int2Type<SwapArgs>());
+ }
+ };
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// class template FunctorDispatcher
+// Implements a logarithmic double dispatcher for functors
+// Features automated casting
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class BaseLhs, class BaseRhs = BaseLhs,
+ typename ResultType = void,
+ template <class, class> class CastingPolicy = DynamicCaster,
+ template <class, class, class, class>
+ class DispatcherBackend = BasicDispatcher>
+ class FunctorDispatcher
+ {
+ typedef LOKI_TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList;
+ typedef Functor<ResultType, ArgsList, LOKI_DEFAULT_THREADING> FunctorType;
+
+ DispatcherBackend<BaseLhs, BaseRhs, ResultType, FunctorType> backEnd_;
+
+ public:
+ template <class SomeLhs, class SomeRhs, class Fun>
+ void Add(const Fun& fun)
+ {
+ typedef Private::FunctorDispatcherHelper<
+ BaseLhs, BaseRhs,
+ SomeLhs, SomeRhs,
+ ResultType,
+ CastingPolicy<SomeLhs, BaseLhs>,
+ CastingPolicy<SomeRhs, BaseRhs>,
+ Fun, false> Adapter;
+
+ backEnd_.template Add<SomeLhs, SomeRhs>(FunctorType(Adapter(fun)));
+ }
+ template <class SomeLhs, class SomeRhs, bool symmetric, class Fun>
+ void Add(const Fun& fun)
+ {
+ Add<SomeLhs,SomeRhs>(fun);
+
+ if (symmetric)
+ {
+ // Note: symmetry only makes sense where BaseLhs==BaseRhs
+ typedef Private::FunctorDispatcherHelper<
+ BaseLhs, BaseLhs,
+ SomeLhs, SomeRhs,
+ ResultType,
+ CastingPolicy<SomeLhs, BaseLhs>,
+ CastingPolicy<SomeRhs, BaseLhs>,
+ Fun, true> AdapterR;
+
+ backEnd_.template Add<SomeRhs, SomeLhs>(FunctorType(AdapterR(fun)));
+ }
+ }
+
+ template <class SomeLhs, class SomeRhs>
+ void Remove()
+ {
+ backEnd_.template Remove<SomeLhs, SomeRhs>();
+ }
+
+ ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
+ {
+ return backEnd_.Go(lhs, rhs);
+ }
+ };
+} // namespace Loki
+
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/NullType.h b/shared/loki/NullType.h
new file mode 100644
index 00000000..9403901a
--- /dev/null
+++ b/shared/loki/NullType.h
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_NULLTYPE_INC_
+#define LOKI_NULLTYPE_INC_
+
+// $Id: NullType.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class NullType
+// Used as a placeholder for "no type here"
+// Useful as an end marker in typelists
+////////////////////////////////////////////////////////////////////////////////
+
+ class NullType {};
+
+} // namespace Loki
+
+
+#endif // end file guardian
diff --git a/shared/loki/OrderedStatic.h b/shared/loki/OrderedStatic.h
new file mode 100644
index 00000000..6eaa20b9
--- /dev/null
+++ b/shared/loki/OrderedStatic.h
@@ -0,0 +1,225 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2005 Peter Kümmel
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_ORDEREDSTATIC_INC_
+#define LOKI_ORDEREDSTATIC_INC_
+
+// $Id: OrderedStatic.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+#include <vector>
+#include <iostream>
+
+#include "LokiExport.h"
+#include "Singleton.h"
+#include "Typelist.h"
+#include "Sequence.h"
+
+// usage: see test/OrderedStatic
+
+namespace Loki
+{
+ namespace Private
+ {
+ ////////////////////////////////////////////////////////////////////////////////
+ // polymorph base class for OrderedStatic template,
+ // necessary because of the creator
+ ////////////////////////////////////////////////////////////////////////////////
+ class LOKI_EXPORT OrderedStaticCreatorFunc
+ {
+ public:
+ virtual void createObject() = 0;
+
+ protected:
+ OrderedStaticCreatorFunc();
+ virtual ~OrderedStaticCreatorFunc();
+
+ private:
+ OrderedStaticCreatorFunc(const OrderedStaticCreatorFunc&);
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // template base clase for OrderedStatic template,
+ // common for all specializations
+ ////////////////////////////////////////////////////////////////////////////////
+ template<class T>
+ class OrderedStaticBase : public OrderedStaticCreatorFunc
+ {
+ public:
+ T& operator*()
+ {
+ return *val_;
+ }
+
+ T* operator->()
+ {
+ return val_;
+ }
+
+ protected:
+
+ OrderedStaticBase(unsigned int longevity) : val_(0), longevity_(longevity)
+ {
+ }
+
+ virtual ~OrderedStaticBase()
+ {
+ }
+
+ void SetLongevity(T* ptr)
+ {
+ val_=ptr;
+ Loki::SetLongevity(val_,longevity_);
+ }
+
+ private:
+ OrderedStaticBase();
+ OrderedStaticBase(const OrderedStaticBase&);
+ OrderedStaticBase& operator=(const OrderedStaticBase&);
+ T* val_;
+ unsigned int longevity_;
+
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // OrderedStaticManagerClass implements details
+ // OrderedStaticManager is then defined as a Singleton
+ ////////////////////////////////////////////////////////////////////////////////
+ class LOKI_EXPORT OrderedStaticManagerClass
+ {
+ public:
+ OrderedStaticManagerClass();
+ virtual ~OrderedStaticManagerClass();
+
+ typedef void (OrderedStaticCreatorFunc::*Creator)();
+
+ void createObjects();
+ void registerObject(unsigned int longevity,OrderedStaticCreatorFunc*,Creator);
+
+ private:
+ OrderedStaticManagerClass(const OrderedStaticManagerClass&);
+ OrderedStaticManagerClass& operator=(const OrderedStaticManagerClass&);
+
+ struct Data
+ {
+ Data(unsigned int,OrderedStaticCreatorFunc*, Creator);
+ unsigned int longevity;
+ OrderedStaticCreatorFunc* object;
+ Creator creator;
+ };
+
+ std::vector<Data> staticObjects_;
+ unsigned int max_longevity_;
+ unsigned int min_longevity_;
+ };
+
+ }// namespace Private
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // OrderedStaticManager is only a Singleton typedef
+ ////////////////////////////////////////////////////////////////////////////////
+
+ typedef Loki::SingletonHolder
+ <
+ Loki::Private::OrderedStaticManagerClass,
+ Loki::CreateUsingNew,
+ Loki::NoDestroy,
+ Loki::SingleThreaded
+ >
+ OrderedStaticManager;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // template OrderedStatic template:
+ // L : longevity
+ // T : object type
+ // TList : creator parameters
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<unsigned int L, class T, class TList = Loki::NullType>
+ class OrderedStatic;
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // OrderedStatic specializations
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<unsigned int L, class T>
+ class OrderedStatic<L, T, Loki::NullType> : public Private::OrderedStaticBase<T>
+ {
+ public:
+ OrderedStatic() : Private::OrderedStaticBase<T>(L)
+ {
+ OrderedStaticManager::Instance().registerObject
+ (L,this,&Private::OrderedStaticCreatorFunc::createObject);
+ }
+
+ void createObject()
+ {
+ Private::OrderedStaticBase<T>::SetLongevity(new T);
+ }
+
+ private:
+ OrderedStatic(const OrderedStatic&);
+ OrderedStatic& operator=(const OrderedStatic&);
+ };
+
+ template<unsigned int L, class T, typename P1>
+ class OrderedStatic<L, T, Loki::Seq<P1> > : public Private::OrderedStaticBase<T>
+ {
+ public:
+ OrderedStatic(P1 p) : Private::OrderedStaticBase<T>(L), para_(p)
+ {
+ OrderedStaticManager::Instance().registerObject
+ (L,this,&Private::OrderedStaticCreatorFunc::createObject);
+ }
+
+ void createObject()
+ {
+ Private::OrderedStaticBase<T>::SetLongevity(new T(para_));
+ }
+
+ private:
+ OrderedStatic();
+ OrderedStatic(const OrderedStatic&);
+ OrderedStatic& operator=(const OrderedStatic&);
+ P1 para_;
+ };
+
+ template<unsigned int L, class T, typename P1>
+ class OrderedStatic<L, T, P1(*)() > : public Private::OrderedStaticBase<T>
+ {
+ public:
+
+ typedef P1(*Func)();
+
+ OrderedStatic(Func p) : Private::OrderedStaticBase<T>(L), para_(p)
+ {
+ OrderedStaticManager::Instance().registerObject
+ (L,this,&Private::OrderedStaticCreatorFunc::createObject);
+ }
+
+ void createObject()
+ {
+ Private::OrderedStaticBase<T>::SetLongevity(new T(para_()));
+ }
+
+ private:
+ OrderedStatic();
+ OrderedStatic(const OrderedStatic&);
+ OrderedStatic& operator=(const OrderedStatic&);
+ Func para_;
+ };
+
+}// namespace Loki
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/Pimpl.h b/shared/loki/Pimpl.h
new file mode 100644
index 00000000..ed0d1c7b
--- /dev/null
+++ b/shared/loki/Pimpl.h
@@ -0,0 +1,198 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 Peter Kümmel
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_PIMPL_INC_
+#define LOKI_PIMPL_INC_
+
+// $Id: Pimpl.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+/// \defgroup PimplGroup Pimpl
+
+#ifndef LOKI_INHERITED_PIMPL_NAME
+#define LOKI_INHERITED_PIMPL_NAME d
+#endif
+
+#ifndef LOKI_INHERITED_RIMPL_NAME
+#define LOKI_INHERITED_RIMPL_NAME d
+#endif
+
+namespace Loki
+{
+
+ //////////////////////////////////////////
+ /// \class ConstPropPtr
+ ///
+ /// \ingroup PimplGroup
+ /// Simple const propagating smart pointer
+ /// Is the default smart pointer of Pimpl.
+ //////////////////////////////////////////
+
+ template<class T>
+ struct ConstPropPtr
+ {
+ explicit ConstPropPtr(T* p) : ptr_(p) {}
+ ~ConstPropPtr() { delete ptr_; ptr_ = 0; }
+ T* operator->() { return ptr_; }
+ T& operator*() { return *ptr_; }
+ const T* operator->() const { return ptr_; }
+ const T& operator*() const { return *ptr_; }
+
+ private:
+ ConstPropPtr();
+ ConstPropPtr(const ConstPropPtr&);
+ ConstPropPtr& operator=(const ConstPropPtr&);
+ T* ptr_;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class Pimpl
+ ///
+ /// \ingroup PimplGroup
+ ///
+ /// Implements the Pimpl idiom. It's a wrapper for a smart pointer which
+ /// automatically creates and deletes the implementation object and adds
+ /// const propagation to the smart pointer.
+ ///
+ /// \par Usage
+ /// see test/Pimpl
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ class T,
+ typename Pointer = ConstPropPtr<T>
+ >
+ class Pimpl
+ {
+ public:
+
+ typedef T Impl;
+
+ Pimpl() : ptr_(new T)
+ {}
+
+ ~Pimpl()
+ {
+ // Don't compile with incomplete type
+ //
+ // If compilation breaks here make sure
+ // the compiler does not auto-generate the
+ // destructor of the class hosting the pimpl:
+ // - implement the destructor of the class
+ // - don't inline the destructor
+ typedef char T_must_be_defined[sizeof(T) ? 1 : -1 ];
+ }
+
+
+ T* operator->()
+ {
+ return ptr_.operator->();
+ }
+
+ T& operator*()
+ {
+ return ptr_.operator*();
+ }
+
+ const T* operator->() const
+ {
+ return ptr_.operator->();
+ }
+
+ const T& operator*() const
+ {
+ return ptr_.operator*();
+ }
+
+ Pointer& wrapped()
+ {
+ return ptr_;
+ }
+
+ const Pointer& wrapped() const
+ {
+ return ptr_;
+ }
+
+
+ private:
+ Pimpl(const Pimpl&);
+ Pimpl& operator=(const Pimpl&);
+
+ Pointer ptr_;
+ };
+
+
+ template<class T, typename Pointer = ConstPropPtr<T> >
+ struct PimplOwner
+ {
+ Pimpl<T,Pointer> LOKI_INHERITED_PIMPL_NAME;
+ };
+
+
+ //////////////////////////////////////////
+ /// \class ImplOf
+ ///
+ /// \ingroup PimplGroup
+ /// Convenience template for the
+ /// implementations which Pimpl points to.
+ //////////////////////////////////////////
+
+ template<class T>
+ struct ImplOf;
+
+
+ //////////////////////////////////////////
+ /// \class PImplOf
+ ///
+ /// \ingroup PimplGroup
+ /// Convenience template which uses ImplOf
+ /// as implementation structure
+ //////////////////////////////////////////
+
+
+ template<class T, template<class> class Ptr = ConstPropPtr>
+ struct PimplOf
+ {
+ typedef T Impl;
+
+ // declare pimpl
+ typedef Pimpl<ImplOf<T>, Ptr<ImplOf<T> > > Type;
+
+ // inherit pimpl
+ typedef PimplOwner<ImplOf<T>, Ptr<ImplOf<T> > > Owner;
+ };
+
+
+ template<class T, class UsedPimpl = typename PimplOf<T>::Type >
+ struct RimplOf
+ {
+ typedef typename UsedPimpl::Impl & Type;
+
+ class Owner
+ {
+ UsedPimpl pimpl;
+
+ public:
+ Owner() : LOKI_INHERITED_RIMPL_NAME(*pimpl)
+ {}
+
+ Type LOKI_INHERITED_RIMPL_NAME;
+ };
+
+ };
+
+}
+
+#endif // end file guardian
+
diff --git a/shared/loki/RefToValue.h b/shared/loki/RefToValue.h
new file mode 100644
index 00000000..248de792
--- /dev/null
+++ b/shared/loki/RefToValue.h
@@ -0,0 +1,70 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 Richard Sposato
+// Copyright (c) 2006 Peter Kümmel
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The authors make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_REFTOVALUE_INC_
+#define LOKI_REFTOVALUE_INC_
+
+// $Id: RefToValue.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+namespace Loki
+{
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class RefToValue
+ ///
+ /// \ingroup SmartPointerGroup
+ /// Transports a reference as a value
+ /// Serves to implement the Colvin/Gibbons trick for SmartPtr/ScopeGuard
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class RefToValue
+ {
+ public:
+
+ RefToValue(T& ref) : ref_(ref)
+ {}
+
+ RefToValue(const RefToValue& rhs) : ref_(rhs.ref_)
+ {}
+
+ operator T& () const
+ {
+ return ref_;
+ }
+
+ private:
+ // Disable - not implemented
+ RefToValue();
+ RefToValue& operator=(const RefToValue&);
+
+ T& ref_;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \ingroup ExceptionGroup
+ /// RefToValue creator.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ inline RefToValue<T> ByRef(T& t)
+ {
+ return RefToValue<T>(t);
+ }
+
+}
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/Register.h b/shared/loki/Register.h
new file mode 100644
index 00000000..0ad014ab
--- /dev/null
+++ b/shared/loki/Register.h
@@ -0,0 +1,134 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 Peter Kümmel
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_REGISTER_INC_
+#define LOKI_REGISTER_INC_
+
+// $Id: Register.h 776 2006-11-09 13:12:57Z syntheticpp $
+
+
+#include "TypeManip.h"
+#include "HierarchyGenerators.h"
+
+/// \defgroup RegisterGroup Register
+
+namespace Loki
+{
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ // Helper classes/functions for RegisterByCreateSet
+ //
+ ////////////////////////////////////////////////////////////////////////////////
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \ingroup RegisterGroup
+ /// Must be specialized be the user
+ ////////////////////////////////////////////////////////////////////////////////
+ template<class t> bool RegisterFunction();
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \ingroup RegisterGroup
+ /// Must be specialized be the user
+ ////////////////////////////////////////////////////////////////////////////////
+ template<class t> bool UnRegisterFunction();
+
+ namespace Private
+ {
+ template<class T>
+ struct RegisterOnCreate
+ {
+ RegisterOnCreate() { RegisterFunction<T>(); }
+ };
+
+ template<class T>
+ struct UnRegisterOnDelete
+ {
+ ~UnRegisterOnDelete() { UnRegisterFunction<T>(); }
+ };
+
+ template<class T>
+ struct RegisterOnCreateElement
+ {
+ RegisterOnCreate<T> registerObj;
+ };
+
+ template<class T>
+ struct UnRegisterOnDeleteElement
+ {
+ UnRegisterOnDelete<T> unregisterObj;
+ };
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class RegisterOnCreateSet
+ ///
+ /// \ingroup RegisterGroup
+ /// Implements a generic register class which registers classes of a typelist
+ ///
+ /// \par Usage
+ /// see test/Register
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename ElementList>
+ struct RegisterOnCreateSet
+ : GenScatterHierarchy<ElementList, Private::RegisterOnCreateElement>
+ {};
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class UnRegisterOnDeleteSet
+ ///
+ /// \ingroup RegisterGroup
+ /// Implements a generic register class which unregisters classes of a typelist
+ ///
+ /// \par Usage
+ /// see test/Register
+ ////////////////////////////////////////////////////////////////////////////////
+ template<typename ElementList>
+ struct UnRegisterOnDeleteSet
+ : GenScatterHierarchy<ElementList, Private::UnRegisterOnDeleteElement>
+ {};
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \def LOKI_CHECK_CLASS_IN_LIST( CLASS , LIST )
+ ///
+ /// \ingroup RegisterGroup
+ /// Check if CLASS is in the typelist LIST.
+ ///
+ /// \par Usage
+ /// see test/Register
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+#define LOKI_CONCATE(a,b,c,d) a ## b ## c ## d
+#define LOKI_CONCAT(a,b,c,d) LOKI_CONCATE(a,b,c,d)
+
+#define LOKI_CHECK_CLASS_IN_LIST( CLASS , LIST ) \
+ \
+ struct LOKI_CONCAT(check_,CLASS,_isInList_,LIST) \
+ { \
+ typedef int LOKI_CONCAT(ERROR_class_,CLASS,_isNotInList_,LIST); \
+ }; \
+ typedef Loki::Select<Loki::TL::IndexOf<LIST, CLASS>::value == -1, \
+ CLASS, \
+ LOKI_CONCAT(check_,CLASS,_isInList_,LIST)> \
+ ::Result LOKI_CONCAT(CLASS,isInList,LIST,result); \
+ typedef LOKI_CONCAT(CLASS,isInList,LIST,result):: \
+ LOKI_CONCAT(ERROR_class_,CLASS,_isNotInList_,LIST) \
+ LOKI_CONCAT(ERROR_class_,CLASS,_isNotInList__,LIST);
+
+
+} // namespace Loki
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/SPCachedFactory.h b/shared/loki/SPCachedFactory.h
new file mode 100644
index 00000000..71c72644
--- /dev/null
+++ b/shared/loki/SPCachedFactory.h
@@ -0,0 +1,204 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 by Guillaume Chatelet
+//
+// Code covered by the MIT License
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+//
+// The authors make no representations about the suitability of this software
+// for any purpose. It is provided "as is" without express or implied warranty.
+//
+// This code DOES NOT accompany the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// $Id: SPCachedFactory.h 896 2008-08-08 22:20:05Z syntheticpp $
+
+#ifndef SPCACHEDFACTORY_H_
+#define SPCACHEDFACTORY_H_
+
+/**
+ * This file is intented to be used if you want a CachedFactory with
+ * a SmartPointer encapsulation policy.
+ * It as been defined in a separate file because of the many introduced
+ * dependencies (SmartPtr.h would depend on Functor.h and CachedFactory.h
+ * would depend on SmartPtr.h). By defining another header you pay for those
+ * extra dependencies only if you need it.
+ *
+ * This file defines FunctionStorage a new SmartPointer storage policy and
+ * SmartPointer a new CachedFactory encapsulation policy.
+ */
+
+#include <loki/Functor.h>
+#include <loki/SmartPtr.h>
+#include <loki/CachedFactory.h>
+
+namespace Loki
+{
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class FunctionStorage
+///
+/// \ingroup SmartPointerStorageGroup
+/// \brief Implementation of the StoragePolicy used by SmartPtr.
+///
+/// This storage policy is used by SmartPointer CachedFactory's encapsulation
+/// policy. It's purpose is to call a Functor instead of deleting the
+/// underlying pointee object. You have to set the callback functor by calling
+/// SetCallBackFunction(const FunctorType &functor).
+///
+/// Unfortunately, the functor argument is not a reference to the SmartPtr but
+/// a void *. Making functor argument a reference to the pointer would require
+/// the FunctionStorage template to know the full definition of the SmartPtr.
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class FunctionStorage
+ {
+ public:
+ /// the type of the pointee_ object
+ typedef T* StoredType;
+ /// type used to declare OwnershipPolicy type.
+ typedef T* InitPointerType;
+ /// type returned by operator->
+ typedef T* PointerType;
+ /// type returned by operator*
+ typedef T& ReferenceType;
+ /// type of the Functor to set
+ typedef Functor< void , Seq< void* > > FunctorType;
+
+ FunctionStorage() : pointee_(Default()), functor_()
+ {}
+
+ // The storage policy doesn't initialize the stored pointer
+ // which will be initialized by the OwnershipPolicy's Clone fn
+ FunctionStorage(const FunctionStorage& rsh) : pointee_(0), functor_(rsh.functor_)
+ {}
+
+ template <class U>
+ FunctionStorage(const FunctionStorage<U>& rsh) : pointee_(0), functor_(rsh.functor_)
+ {}
+
+ FunctionStorage(const StoredType& p) : pointee_(p), functor_() {}
+
+ PointerType operator->() const { return pointee_; }
+
+ ReferenceType operator*() const { return *pointee_; }
+
+ void Swap(FunctionStorage& rhs)
+ {
+ std::swap(pointee_, rhs.pointee_);
+ std::swap(functor_, rhs.functor_);
+ }
+
+ /// Sets the callback function to call. You have to specify it or
+ /// the smartPtr will throw a bad_function_call exception.
+ void SetCallBackFunction(const FunctorType &functor)
+ {
+ functor_ = functor;
+ }
+
+ // Accessors
+ template <class F>
+ friend typename FunctionStorage<F>::PointerType GetImpl(const FunctionStorage<F>& sp);
+
+ template <class F>
+ friend const typename FunctionStorage<F>::StoredType& GetImplRef(const FunctionStorage<F>& sp);
+
+ template <class F>
+ friend typename FunctionStorage<F>::StoredType& GetImplRef(FunctionStorage<F>& sp);
+
+ protected:
+ // Destroys the data stored
+ // (Destruction might be taken over by the OwnershipPolicy)
+ void Destroy()
+ {
+ functor_(this);
+ }
+
+ // Default value to initialize the pointer
+ static StoredType Default()
+ { return 0; }
+
+ private:
+ // Data
+ StoredType pointee_;
+ FunctorType functor_;
+ };
+
+ template <class T>
+ inline typename FunctionStorage<T>::PointerType GetImpl(const FunctionStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline const typename FunctionStorage<T>::StoredType& GetImplRef(const FunctionStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline typename FunctionStorage<T>::StoredType& GetImplRef(FunctionStorage<T>& sp)
+ { return sp.pointee_; }
+
+ /**
+ * \class SmartPointer
+ * \ingroup EncapsulationPolicyCachedFactoryGroup
+ * \brief Encapsulate the object in a SmartPtr with FunctionStorage policy.
+ *
+ * The object will come back to the Cache as soon as no more SmartPtr are
+ * referencing this object. You can customize the SmartPointer with the standard
+ * SmartPtr policies (OwnershipPolicy, ConversionPolicy, CheckingPolicy,
+ * ConstnessPolicy) but StoragePolicy is forced to FunctionStorage.
+ */
+ template
+ <
+ class AbstractProduct,
+ template <class> class OwnershipPolicy = RefCounted,
+ class ConversionPolicy = DisallowConversion,
+ template <class> class CheckingPolicy = AssertCheck,
+ template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
+ >
+ class SmartPointer
+ {
+ private:
+ typedef SmartPtr< AbstractProduct,OwnershipPolicy,
+ ConversionPolicy, CheckingPolicy,
+ FunctionStorage, ConstnessPolicy > CallBackSP;
+ protected:
+ typedef CallBackSP ProductReturn;
+ SmartPointer() : fun(this, &SmartPointer::smartPointerCallbackFunction) {}
+ virtual ~SmartPointer(){}
+
+ ProductReturn encapsulate(AbstractProduct* pProduct)
+ {
+ CallBackSP SP(pProduct);
+ SP.SetCallBackFunction(fun);
+ return SP;
+ }
+
+ AbstractProduct* release(ProductReturn &pProduct)
+ {
+ return GetImpl(pProduct);
+ }
+
+ const char* name(){return "smart pointer";}
+
+ private:
+ SmartPointer& operator=(const SmartPointer&);
+ SmartPointer(const SmartPointer&);
+ void smartPointerCallbackFunction(void* pSP)
+ {
+ CallBackSP &SP(*reinterpret_cast<CallBackSP*>(pSP));
+ ReleaseObject(SP);
+ }
+ virtual void ReleaseObject(ProductReturn &object)=0;
+ const typename CallBackSP::FunctorType fun;
+ };
+
+} // namespace Loki
+
+#endif /*SPCACHEDFACTORY_H_*/
diff --git a/shared/loki/SafeBits.h b/shared/loki/SafeBits.h
new file mode 100644
index 00000000..f45065ed
--- /dev/null
+++ b/shared/loki/SafeBits.h
@@ -0,0 +1,514 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2009 by Fedor Pikus & Rich Sposato
+// The copyright on this file is protected under the terms of the MIT license.
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+//
+// The author makes no claims about the suitability of this software for any
+// purpose. It is provided "as is" without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+
+// $Id$
+
+
+#ifndef LOKI_INCLUDED_SAFE_BIT_FIELDS_H
+#define LOKI_INCLUDED_SAFE_BIT_FIELDS_H
+
+#include <cstdlib>
+#include <assert.h>
+#include <loki/static_check.h>
+
+
+namespace Loki
+{
+
+/*
+ ==========================================================================================================================================
+ SafeBitField - type-safe class for bit fields.
+ SafeBitConst - type-safe class for bit constants.
+ SafeBitField is designed to be a [almost] drop-in replacement for integer flags and bit fields where individual bits are set and checked
+ using symbolic names for flags:
+
+ typedef unsigned long Labels_t;
+ Labels_t labels;
+ const Labels_t Label_A = 0x00000001;
+ const Labels_t Label_B = 0x00000002;
+ ...
+ labels |= Label_B;
+ if ( labels & Label_A ) { ... }
+
+ Such code offers no protection against mismatching bit constants and bit fields:
+
+ typedef unsigned long Kinds_t;
+ Kinds_t kinds;
+ const Kinds_t Kind_A = 0x00000004;
+ ...
+ if ( kinds & Label_A ) { ... } // Error but compiles
+
+ SafeBitField is a drop-in replacement which generates a unique type for each bit field. Bit fields of different types cannot be applied
+ to each other:
+
+ LOKI_BIT_FIELD( unsigned long ) Labels_t;
+ Labels_t labels;
+ LOKI_BIT_CONST( Labels_t, Label_A, 1 ); // 0x0001 - 1st bit is set
+ LOKI_BIT_CONST( Labels_t, Label_B, 2 ); // 0x0002 - 1st bit is set
+ ...
+ LOKI_BIT_FIELD( unsigned long ) Kinds_t;
+ Kinds_t kinds;
+ LOKI_BIT_CONST( Kinds_t, Kind_A, 3 ); // 0x0004 - 1st bit is set
+ ...
+ if ( kinds & Label_A ) { ... } // Does not compile
+
+ Several other kinds of bit field misuse are caught by safe bit fields:
+
+ if ( kinds & Kind_A == 0 ) { ... }
+ if ( kinds && Kind_A ) { ... }
+
+ There are few cases where drop-in replacement does not work:
+
+ 1. Operations involving bit fields and unnamed integers. Usually the integer in question is 0:
+
+ Labels_t labels = 0; // No longer compiles
+ if ( ( labels & Label_A ) == 0 ) { ... } // Also does not compile
+
+ The solution is to use named bit constants, including the one for 0:
+
+ LOKI_BIT_CONST( Labels_t, Label_None, 0 ); // 0x0000 - No bit is set
+ Labels_t labels = Label_None; // Or just Labels_t labels; - constructor initializes to 0
+ if ( ( labels & Label_A ) == Label_None ) { ... } // // Or just if ( labels & Label_A ) { ... }
+
+ 2. I/O and other operations which require integer variables and cannot be modified:
+
+ void write_to_db( unsigned int word );
+ Labels_t labels;
+ write_to_db( labels ); // No longer compiles
+
+ This problem is solved by reinterpreting the bit fields as an integer, the user is responsible for using the right
+ type of integer:
+
+ write_to_db( *((Labels_t::bit_word_t*)(&labels)) );
+
+ ==========================================================================================================================================
+*/
+
+/// @par Non-Templated Initialization.
+/// Not all compilers support template member functions where the template
+/// arguments are not deduced but explicitly specified. For these broken
+/// compilers, a non-template make_bit_const() function is provided instead of
+/// the template one. The only downside is that instead of compile-time checking
+/// of the index argument, it does runtime checking.
+#if defined(__SUNPRO_CC) || ( defined(__GNUC__) && (__GNUC__ < 3) )
+ #define LOKI_BIT_FIELD_NONTEMPLATE_INIT
+#endif
+
+/// @par Forbidding Conversions.
+/// This incomplete type prevents compilers from instantiating templates for
+/// type conversions which should not happen. This incomplete type must be a
+/// template: if the type is incomplete at the point of template definition,
+/// the template is illegal (although the standard allows compilers to accept
+/// or reject such code, §14.6/, so some compilers will not issue diagnostics
+/// unless template is instantiated). The standard-compliant way is to defer
+/// binding to the point of instantiation by making the incomplete type itself
+/// a template.
+template < typename > struct Forbidden_conversion; // This struct must not be defined!
+
+/// Forward declaration of the field type.
+template <
+ unsigned int unique_index,
+ typename word_t = unsigned long
+> class SafeBitField;
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SafeBitConst Bit constants.
+/// This class defines a bit-field constant - a collection of unchanging bits
+/// used to compare to bit-fields. Instances of this class are intended to act
+/// as labels for bit-fields.
+///
+/// \par Safety
+/// - This class provides operations used for comparisons and conversions, but
+/// no operations which may modify the value.
+/// - As a templated class, it provides type-safety so bit values and constants
+/// used for different reasons may not be unknowingly compared to each other.
+/// - The unique_index template parameter insures the unique type of each bit
+/// bit-field. It shares the unique_index with a similar SafeBitField.
+/// - Its operations only allow comparisons to other bit-constants and
+/// bit-fields of the same type.
+////////////////////////////////////////////////////////////////////////////////
+
+template
+<
+ unsigned int unique_index,
+ typename word_t = unsigned long
+>
+class SafeBitConst
+{
+public:
+
+ /// Type of the bit field is available if needed.
+ typedef word_t bit_word_t;
+ /// Corresponding field type.
+ typedef SafeBitField< unique_index, word_t > field_t;
+ /// Typedef is not allowed in friendship declaration.
+ friend class SafeBitField< unique_index, word_t >;
+
+ // Static factory constructor, creates a bit constant with one bit set. The position of the bit is given by the template parameter,
+ // bit 1 is the junior bit, i.e. make_bit_const<1>() returns 1. Bit index 0 is a special case and returns 0.
+ // This function should be used only to initialize the static bit constant objects.
+ // This function will not compile if the bit index is outside the vaild range.
+ // There is also a compile-time assert to make sure the size of the class is the same as the size of the underlaying integer type.
+ // This assert could go into the constructor, but aCC does not seem to understand sizeof(SafeBitConst) in the constructor.
+ //
+#ifndef LOKI_BIT_FIELD_NONTEMPLATE_INIT
+ template < unsigned int i > static SafeBitConst make_bit_const()
+ {
+ LOKI_STATIC_CHECK( i <= ( 8 * sizeof(word_t) ), Index_is_beyond_size_of_data );
+ LOKI_STATIC_CHECK( sizeof(SafeBitConst) == sizeof(word_t), Object_size_does_not_match_data_size );
+ // Why check for ( i > 0 ) again inside the shift if the shift
+ // can never be evaluated for i == 0? Some compilers see shift by ( i - 1 )
+ // and complain that for i == 0 the number is invalid, without
+ // checking that shift needs evaluating.
+ return SafeBitConst( ( i > 0 ) ? ( word_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0 );
+ }
+#else
+ static SafeBitConst make_bit_const( unsigned int i )
+ {
+ LOKI_STATIC_CHECK( sizeof(SafeBitConst) == sizeof(word_t), Object_size_does_not_match_data_size );
+ assert( i <= ( 8 * sizeof(word_t) ) ); // Index is beyond size of data.
+ // Why check for ( i > 0 ) again inside the shift if the shift
+ // can never be evaluated for i == 0? Some compilers see shift by ( i - 1 )
+ // and complain that for i == 0 the number is invalid, without
+ // checking that shift needs evaluating.
+ return SafeBitConst( ( i > 0 ) ? ( word_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0 );
+ }
+#endif
+
+ /// Default constructor allows client code to construct bit fields on the stack.
+ SafeBitConst() : word( 0 ) {}
+
+ /// Copy constructor.
+ SafeBitConst( const SafeBitConst& rhs ) : word( rhs.word ) {}
+
+ /// Comparison operators which take a constant bit value.
+ bool operator == ( const SafeBitConst & rhs ) const { return word == rhs.word; }
+ bool operator != ( const SafeBitConst & rhs ) const { return word != rhs.word; }
+ bool operator < ( const SafeBitConst & rhs ) const { return word < rhs.word; }
+ bool operator > ( const SafeBitConst & rhs ) const { return word > rhs.word; }
+ bool operator <= ( const SafeBitConst & rhs ) const { return word <= rhs.word; }
+ bool operator >= ( const SafeBitConst & rhs ) const { return word >= rhs.word; }
+
+ /// Comparision operators for mutable bit fields.
+ bool operator == ( const field_t & rhs ) const { return word == rhs.word; }
+ bool operator != ( const field_t & rhs ) const { return word != rhs.word; }
+ bool operator < ( const field_t & rhs ) const { return word < rhs.word; }
+ bool operator > ( const field_t & rhs ) const { return word > rhs.word; }
+ bool operator <= ( const field_t & rhs ) const { return word <= rhs.word; }
+ bool operator >= ( const field_t & rhs ) const { return word >= rhs.word; }
+
+ /// Bitwise operations. Operation-assignment operators are not needed,
+ /// since bit constants cannot be changed after they are initialized.
+ const SafeBitConst operator | ( const SafeBitConst & rhs ) const { return SafeBitConst( word | rhs.word ); }
+ const SafeBitConst operator & ( const SafeBitConst & rhs ) const { return SafeBitConst( word & rhs.word ); }
+ const SafeBitConst operator ^ ( const SafeBitConst & rhs ) const { return SafeBitConst( word ^ rhs.word ); }
+ const SafeBitConst operator ~ ( void ) const { return SafeBitConst( ~word ); }
+
+ /// These bitwise operators return a bit-field instead of a bit-const.
+ field_t operator | ( const field_t & rhs ) const { return field_t( word | rhs.word ); }
+ field_t operator & ( const field_t & rhs ) const { return field_t( word & rhs.word ); }
+ field_t operator ^ ( const field_t & rhs ) const { return field_t( word ^ rhs.word ); }
+
+ /// The shift operators move bits inside the bit field. These are useful in
+ /// loops which act over bit fields and increment them.
+ const SafeBitConst operator << ( unsigned int s ) const { return SafeBitConst( word << s ); }
+ const SafeBitConst operator >> ( unsigned int s ) const { return SafeBitConst( word >> s ); }
+
+ /// Word size is also the maximum number of different bit fields for a given word type.
+ static size_t size() { return ( 8 * sizeof( word_t ) ); }
+
+private:
+
+ /// Copy-assignment operator is not implemented since it does not make sense
+ /// for a constant object.
+ SafeBitConst operator = ( const SafeBitConst & rhs );
+
+ // Private constructor from an integer type.
+ explicit SafeBitConst( word_t init ) : word( init ) {}
+
+ /// This data stores a single bit value. It is declared const to enforce
+ // constness for all functions of this class.
+ const word_t word;
+
+ // Here comes the interesting stuff: all the operators designed to
+ // trap unintended conversions and make them not compile.
+ // Operators below handle code like this:
+ // SafeBitField<1> label1;
+ // SafeBitField<2> label2;
+ // if ( label1 & label2 ) { ... }
+
+ // These operators are private, and will not instantiate in any
+ // event because of the incomplete Forbidden_conversion struct.
+ template < typename T > SafeBitConst operator|( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitConst operator&( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitConst operator^( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitConst operator|=( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitConst operator&=( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitConst operator^=( T ) const { Forbidden_conversion< T > wrong; return *this; }
+
+ // And the same thing for comparisons: private and unusable.
+ // if ( label1 == label2 ) { ... }
+ template < typename T > bool operator==( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator!=( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator<( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator>( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator<=( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator>=( const T ) const { Forbidden_conversion< T > wrong; return true; }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SafeBitConst Bit constants.
+/// This class defines a bit-field constant - a collection of unchanging bits
+/// used to compare to bit-fields. Instances of this class are intended to
+/// store bit values.
+///
+/// \par Safety
+/// - This class provides operations used for comparisons and conversions, and
+/// also operations which may safely modify the value.
+/// - As a templated class, it provides type-safety so bit values and constants
+/// used for different reasons may not be unknowingly compared to each other.
+/// - The unique_index template parameter insures the unique type of each bit
+/// bit-field. It shares the unique_index with a similar SafeBitConst.
+/// - Its operations only allow comparisons to other bit-constants and
+/// bit-fields of the same type.
+////////////////////////////////////////////////////////////////////////////////
+
+template
+<
+ unsigned int unique_index,
+ typename word_t
+>
+class SafeBitField
+{
+public:
+
+ /// Type of the bit field is available if needed.
+ typedef word_t bit_word_t;
+ /// Corresponding field type.
+ typedef SafeBitConst< unique_index, word_t > const_t;
+ /// Typedef is not allowed in friendship declaration.
+ friend class SafeBitConst<unique_index, word_t>;
+
+ /// Default constructor allows client code to construct bit fields on the stack.
+ SafeBitField() : word( 0 ) {}
+
+ /// Copy constructor and assignment operators.
+ SafeBitField( const SafeBitField & rhs ) : word( rhs.word ) {}
+ SafeBitField & operator = ( const SafeBitField & rhs ) { word = rhs.word; return *this; }
+
+ /// Copy constructor and assignment operators from constant bit fields.
+ SafeBitField( const const_t & rhs ) : word( rhs.word ) {}
+ SafeBitField & operator = ( const const_t & rhs ) { word = rhs.word; return *this; }
+
+ /// These comparison operators act on bit-fields of the same type.
+ bool operator == ( const SafeBitField & rhs ) const { return word == rhs.word; }
+ bool operator != ( const SafeBitField & rhs ) const { return word != rhs.word; }
+ bool operator < ( const SafeBitField & rhs ) const { return word < rhs.word; }
+ bool operator > ( const SafeBitField & rhs ) const { return word > rhs.word; }
+ bool operator <= ( const SafeBitField & rhs ) const { return word <= rhs.word; }
+ bool operator >= ( const SafeBitField & rhs ) const { return word >= rhs.word; }
+
+ /// These comparison operators act on bit-constants of a similar type.
+ bool operator == ( const const_t & rhs ) const { return word == rhs.word; }
+ bool operator != ( const const_t & rhs ) const { return word != rhs.word; }
+ bool operator < ( const const_t & rhs ) const { return word < rhs.word; }
+ bool operator > ( const const_t & rhs ) const { return word > rhs.word; }
+ bool operator <= ( const const_t & rhs ) const { return word <= rhs.word; }
+ bool operator >= ( const const_t & rhs ) const { return word >= rhs.word; }
+
+ /// Bitwise operations that use bit-fields.
+ SafeBitField operator | ( const SafeBitField & rhs ) const { return SafeBitField( word | rhs.word ); }
+ SafeBitField operator & ( const SafeBitField & rhs ) const { return SafeBitField( word & rhs.word ); }
+ SafeBitField operator ^ ( const SafeBitField & rhs ) const { return SafeBitField( word ^ rhs.word ); }
+ SafeBitField operator ~ ( void ) const { return SafeBitField( ~word ); }
+ SafeBitField operator |= ( const SafeBitField & rhs ) { word |= rhs.word; return SafeBitField( *this ); }
+ SafeBitField operator &= ( const SafeBitField & rhs ) { word &= rhs.word; return SafeBitField( *this ); }
+ SafeBitField operator ^= ( const SafeBitField & rhs ) { word ^= rhs.word; return SafeBitField( *this ); }
+
+ /// Bitwise operators that use bit-constants.
+ SafeBitField operator | ( const_t rhs ) const { return SafeBitField( word | rhs.word ); }
+ SafeBitField operator & ( const_t rhs ) const { return SafeBitField( word & rhs.word ); }
+ SafeBitField operator ^ ( const_t rhs ) const { return SafeBitField( word ^ rhs.word ); }
+ SafeBitField operator |= ( const_t rhs ) { word |= rhs.word; return SafeBitField( *this ); }
+ SafeBitField operator &= ( const_t rhs ) { word &= rhs.word; return SafeBitField( *this ); }
+ SafeBitField operator ^= ( const_t rhs ) { word ^= rhs.word; return SafeBitField( *this ); }
+
+ // Conversion to bool.
+ // This is a major source of headaches, but it's required to support code like this:
+ // const static SafeBitConst<1> Label_value = SafeBitConst<1>::make_bit_const<1>();
+ // SafeBitField<1> label;
+ // if ( label & Label_value ) { ... } // Nice...
+ //
+ // The downside is that this allows all sorts of nasty conversions. Without additional precautions, bit fields of different types
+ // can be converted to bool and then compared or operated on:
+ // SafeBitField<1> label1;
+ // SafeBitField<2> label2;
+ // if ( label1 == label2 ) { ... } // Yuck!
+ // if ( label1 & label2 ) { ... } // Blech!
+ //
+ // It is somewhat safer to convert to a pointer, at least pointers to different types cannot be readilly compared, and there are no
+ // bitwise operations on pointers, but the conversion from word_t to a pointer can have run-time cost if they are of different size.
+ //
+ operator const bool() const { return ( 0 != word ); }
+
+ // Shift operators shift bits inside the bit field. Does not make
+ // sense, most of the time, except perhaps to loop over labels and
+ // increment them.
+ SafeBitField operator << ( unsigned int s ) { return SafeBitField( word << s ); }
+ SafeBitField operator >> ( unsigned int s ) { return SafeBitField( word >> s ); }
+ SafeBitField operator <<= ( unsigned int s ) { word <<= s; return *this; }
+ SafeBitField operator >>= ( unsigned int s ) { word >>= s; return *this; }
+
+ // Word size is also the maximum number of different bit fields for
+ // a given word type.
+ static size_t size( void ) { return ( 8 * sizeof( word_t ) ); }
+
+private:
+
+ /// Private constructor from an integer type. Don't put too much stock into
+ /// explicit declaration, it's better than nothing but does not solve all
+ /// problems with undesired conversions because SafeBitField coverts to bool.
+ explicit SafeBitField( word_t init ) : word( init ) {}
+
+ /// This stores the bits.
+ word_t word;
+
+ // Here comes the interesting stuff: all the operators designed to
+ // trap unintended conversions and make them not compile.
+ // Operators below handle code like this:
+ // SafeBitField<1> label1;
+ // SafeBitField<2> label2;
+ // if ( label1 & label2 ) { ... }
+
+ // These operators are private, and will not instantiate in any
+ // event because of the incomplete Forbidden_conversion struct.
+ template < typename T > SafeBitField operator | ( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitField operator & ( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitField operator ^ ( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitField operator |= ( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitField operator &= ( T ) const { Forbidden_conversion< T > wrong; return *this; }
+ template < typename T > SafeBitField operator ^= ( T ) const { Forbidden_conversion< T > wrong; return *this; }
+
+ // And the same thing for comparisons:
+ // if ( label1 == label2 ) { ... }
+ template < typename T > bool operator == ( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator != ( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator < ( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator > ( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator <= ( const T ) const { Forbidden_conversion< T > wrong; return true; }
+ template < typename T > bool operator >= ( const T ) const { Forbidden_conversion< T > wrong; return true; }
+};
+
+// The above template member operators catch errors when the first
+// argument to a binary operator is a label, but they don't work when
+// the first argument is an integer and the second one is a label: the
+// label converts to bool and the operator is performed on two integers.
+// These operators catch errors like this:
+// SafeBitField<1> label1;
+// SafeBitField<2> label2;
+// if ( !label1 & label2 ) { ... }
+// where the first label is converted to bool (these errors cannot be
+// caught by member operators of SafeBitField class because the first
+// argument is not SafeBitField but bool.
+//
+// If used, these operators will not instantiate because of the
+// incomplete Forbidden_conversion struct.
+
+template < unsigned int unique_index, typename word_t >
+inline SafeBitField< unique_index, word_t > operator & ( bool, SafeBitField< unique_index, word_t > rhs )
+{
+ Forbidden_conversion<word_t> wrong;
+ return rhs;
+}
+
+template < unsigned int unique_index, typename word_t >
+inline SafeBitField< unique_index, word_t > operator | ( bool, SafeBitField< unique_index, word_t > rhs )
+{
+ Forbidden_conversion< word_t > wrong;
+ return rhs;
+}
+
+template < unsigned int unique_index, typename word_t >
+inline SafeBitField< unique_index, word_t > operator ^ ( bool, SafeBitField< unique_index, word_t > rhs )
+{
+ Forbidden_conversion< word_t > wrong;
+ return rhs;
+}
+
+template < unsigned int unique_index, typename word_t >
+inline SafeBitField< unique_index, word_t > operator == ( bool, SafeBitField< unique_index, word_t > rhs )
+{
+ Forbidden_conversion< word_t > wrong;
+ return rhs;
+}
+
+template < unsigned int unique_index, typename word_t >
+inline SafeBitField< unique_index, word_t > operator != ( bool, SafeBitField< unique_index, word_t > rhs )
+{
+ Forbidden_conversion< word_t > wrong;
+ return rhs;
+}
+
+// Finally, few macros. All macros are conditionally defined to use the SafeBitField classes if LOKI_SAFE_BIT_FIELD is defined. Otherwise,
+// the macros fall back on the use of typedefs and integer constants. This provides no addititonal safety but allows the code to support the
+// mixture of compilers which are broken to different degrees.
+#define LOKI_SAFE_BIT_FIELD
+
+// The first macro helps to declare new bit field types:
+// LOKI_BIT_FIELD( ulong ) field_t;
+// This creates a typedef field_t for SafeBitField<unique_index, ulong> where index is the current line number. Since line numbers __LINE__ are counted
+// separately for all header files, this ends up being the same type in all files using the header which defines field_t.
+#ifdef LOKI_SAFE_BIT_FIELD
+ #define LOKI_BIT_FIELD( word_t ) typedef SafeBitField<__LINE__, word_t>
+#else
+ #define LOKI_BIT_FIELD( word_t ) typedef word_t
+#endif // LOKI_SAFE_BIT_FIELD
+
+// The second macro helps to declare static bit constants:
+// LOKI_BIT_CONST( field_t, Label_1, 1 );
+// creates new bit field object named Label_1 of type field_t which represents the field with the 1st (junior) bit set.
+#ifdef LOKI_SAFE_BIT_FIELD
+ #ifndef LOKI_BIT_FIELD_NONTEMPLATE_INIT
+ #define LOKI_BIT_CONST( field_t, label, bit_index ) \
+ static const field_t::const_t label = field_t::const_t::make_bit_const<bit_index>()
+ #else
+ #define LOKI_BIT_CONST( field_t, label, bit_index ) \
+ static const field_t::const_t label = field_t::const_t::make_bit_const( bit_index )
+ #endif // LOKI_BIT_FIELD_NONTEMPLATE_INIT
+#else
+ inline size_t make_bit_const( size_t i ) { return ( i > 0 ) ? ( size_t(1) << ( ( i > 0 ) ? ( i - 1 ) : 0 ) ) : 0; }
+ #define LOKI_BIT_CONST( field_t, label, bit_index ) static const field_t label = make_bit_const( bit_index )
+#endif // LOKI_SAFE_BIT_FIELD
+
+// The third macro helps to declare complex bit constants which are combination of several bits:
+// LOKI_BIT_CONSTS( field_t, Label12 ) = Label_1 | Label_2;
+#ifdef LOKI_SAFE_BIT_FIELD
+ #define LOKI_BIT_CONSTS( field_t, label ) static const field_t::const_t label
+#else
+ #define LOKI_BIT_CONSTS( field_t, label ) static const field_t label
+#endif // LOKI_SAFE_BIT_FIELD
+
+// The fourth macro helps to declare the maximum number of bit constants for a given type:
+// static const size_t count = LOKI_BIT_FIELD_COUNT( field_t );
+// declared a variable "count" initialized to field_t::size()
+#ifdef LOKI_SAFE_BIT_FIELD
+ #define LOKI_BIT_FIELD_COUNT( field_t ) field_t::size()
+#else
+ #define LOKI_BIT_FIELD_COUNT( field_t ) ( 8 * sizeof(field_t) )
+#endif // LOKI_SAFE_BIT_FIELD
+
+} // namespace Loki
+
+#endif // LOKI_INCLUDED_SAFE_BIT_FIELDS_H
diff --git a/shared/loki/SafeFormat.h b/shared/loki/SafeFormat.h
new file mode 100644
index 00000000..9d948581
--- /dev/null
+++ b/shared/loki/SafeFormat.h
@@ -0,0 +1,590 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2005 by Andrei Alexandrescu
+// Copyright (c) 2006 Peter Kümmel
+// Permission to use, copy, modify, distribute, and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the suitability of this software
+// for any purpose. It is provided "as is" without express or implied
+// warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_SAFEFORMAT_INC_
+#define LOKI_SAFEFORMAT_INC_
+
+// $Id: SafeFormat.h 911 2008-12-15 20:55:24Z syntheticpp $
+
+
+////////////////////////////////////////////////////////////////////////////////
+// This file contains definitions for SafePrintf. SafeScanf coming soon (the
+// design is similar).
+// See Alexandrescu, Andrei: Type-safe Formatting, C/C++ Users Journal, Aug 2005
+////////////////////////////////////////////////////////////////////////////////
+
+#include <cstdio>
+#include <climits>
+#include <string>
+#include <cstring>
+#include <stdexcept>
+#include <utility>
+#include <cassert>
+#include <locale>
+#include <iostream>
+
+#include <loki/LokiExport.h>
+
+
+// long is 32 bit on 64-bit Windows!
+// intptr_t used to get 64 bit on Win64
+#if defined(_WIN32) || defined(_WIN64)
+# define LOKI_SAFEFORMAT_SIGNED_LONG intptr_t
+# define LOKI_SAFEFORMAT_UNSIGNED_LONG uintptr_t
+#else
+# define LOKI_SAFEFORMAT_SIGNED_LONG signed long
+# define LOKI_SAFEFORMAT_UNSIGNED_LONG unsigned long
+#endif
+
+// Windows headers could have min/max defined
+#ifdef max
+# undef max
+#endif
+#ifdef min
+# undef min
+#endif
+
+namespace Loki
+{
+
+ // Crude writing method: writes straight to the file, unbuffered
+ // Must be combined with a buffer to work properly (and efficiently)
+ LOKI_EXPORT
+ void write(std::FILE* f, const char* from, const char* to);
+
+ // Write to an ostream
+ LOKI_EXPORT
+ void write(std::ostream& f, const char* from, const char* to);
+
+ // Write to a string
+ LOKI_EXPORT
+ void write(std::string& s, const char* from, const char* to);
+
+ // Write to a fixed-size buffer
+ template <class Char>
+ void write(std::pair<Char*, std::size_t>& s, const Char* from, const Char* to) {
+ assert(from <= to);
+ if(from + s.second < to)
+ throw std::overflow_error("");
+ // s.first: position one past the final copied element
+ s.first = std::copy(from, to, s.first);
+ // remaining buffer size
+ s.second -= to - from;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // PrintfState class template
+ // Holds the formatting state, and implements operator() to format stuff
+ // Todo: make sure errors are handled properly
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class Device, class Char>
+ struct PrintfState {
+ PrintfState(Device dev, const Char * format)
+ : device_(dev)
+ , format_(format)
+ , width_(0)
+ , prec_(0)
+ , flags_(0)
+ , result_(0) {
+ Advance();
+ }
+
+ ~PrintfState() {
+ }
+
+ #define LOKI_PRINTF_STATE_FORWARD(type) \
+ PrintfState& operator()(type par) {\
+ return (*this)(static_cast< LOKI_SAFEFORMAT_UNSIGNED_LONG >(par)); \
+ }
+
+ LOKI_PRINTF_STATE_FORWARD(bool)
+ LOKI_PRINTF_STATE_FORWARD(char)
+ LOKI_PRINTF_STATE_FORWARD(signed char)
+ LOKI_PRINTF_STATE_FORWARD(unsigned char)
+ LOKI_PRINTF_STATE_FORWARD(signed short)
+ LOKI_PRINTF_STATE_FORWARD(unsigned short)
+ LOKI_PRINTF_STATE_FORWARD(signed int)
+ LOKI_PRINTF_STATE_FORWARD(signed long)
+#if (defined(_WIN32) || defined(_WIN64))
+ LOKI_PRINTF_STATE_FORWARD(unsigned long)
+#else
+ // on Windows already defined by uintptr_t
+ LOKI_PRINTF_STATE_FORWARD(unsigned int)
+#endif
+
+ // Print (or gobble in case of the "*" specifier) an int
+ PrintfState& operator()(LOKI_SAFEFORMAT_UNSIGNED_LONG i) {
+ if (result_ == -1) return *this; // don't even bother
+ // % [flags] [width] [.prec] [modifier] type_char
+ // Fetch the flags
+ ReadFlags();
+ if (*format_ == '*') {
+ // read the width and get out
+ SetWidth(static_cast<size_t>(i));
+ ++format_;
+ return *this;
+ }
+ ReadWidth();
+ // precision
+ if (*format_ == '.') {
+ // deal with precision
+ if (format_[1] == '*') {
+ // read the precision and get out
+ SetPrec(static_cast<size_t>(i));
+ format_ += 2;
+ return *this;
+ }
+ ReadPrecision();
+ }
+ ReadModifiers();
+ // input size modifier
+ if (ForceShort()) {
+ // short int
+ const Char c = *format_;
+ if (c == 'x' || c == 'X' || c == 'u' || c == 'o') {
+ i = static_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(static_cast<unsigned short>(i));
+ }
+ }
+ FormatWithCurrentFlags(i);
+ return *this;
+ }
+
+ PrintfState& operator()(void* n) {
+ if (result_ == -1) return *this; // don't even bother
+ PrintUsing_snprintf(n,"p");
+ return *this;
+ }
+
+ PrintfState& operator()(double n) {
+ if (result_ == -1) return *this; // don't even bother
+ PrintUsing_snprintf(n,"eEfgG");
+ return *this;
+ }
+
+ PrintfState& operator()(long double n) {
+ if (result_ == -1) return *this; // don't even bother
+ PrintUsing_snprintf(n,"eEfgG");
+ return *this;
+ }
+
+ // Store the number of characters printed so far
+ PrintfState& operator()(int * pi) {
+ return StoreCountHelper(pi);
+ }
+
+ // Store the number of characters printed so far
+ PrintfState& operator()(short * pi) {
+ return StoreCountHelper(pi);
+ }
+
+ // Store the number of characters printed so far
+ PrintfState& operator()(long * pi) {
+ return StoreCountHelper(pi);
+ }
+
+ PrintfState& operator()(const std::string& stdstr) {
+ return operator()(stdstr.c_str());
+ }
+
+ PrintfState& operator()(const char *const s) {
+ if (result_ == -1) return *this;
+ ReadLeaders();
+ const char fmt = *format_;
+ if (fmt == 'p') {
+ FormatWithCurrentFlags(reinterpret_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(s));
+ return *this;
+ }
+ if (fmt != 's') {
+ result_ = -1;
+ return *this;
+ }
+ const size_t len = std::min(std::strlen(s), prec_);
+ if (width_ > len) {
+ if (LeftJustify()) {
+ Write(s, s + len);
+ Fill(' ', width_ - len);
+ } else {
+ Fill(' ', width_ - len);
+ Write(s, s + len);
+ }
+ } else {
+ Write(s, s + len);
+ }
+ Next();
+ return *this;
+ }
+
+ PrintfState& operator()(const void *const p) {
+ return (*this)(reinterpret_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(p));
+ }
+
+ // read the result
+ operator int() const {
+ return static_cast<int>(result_);
+ }
+
+ private:
+ PrintfState& operator=(const PrintfState&);
+ template <typename T>
+ PrintfState& StoreCountHelper(T *const pi) {
+ if (result_ == -1) return *this; // don't even bother
+ ReadLeaders();
+ const char fmt = *format_;
+ if (fmt == 'p') { // pointer
+ FormatWithCurrentFlags(reinterpret_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(pi));
+ return *this;
+ }
+ if (fmt != 'n') {
+ result_ = -1;
+ return *this;
+ }
+ assert(pi != 0);
+ *pi = result_;
+ Next();
+ return *this;
+ }
+
+ void FormatWithCurrentFlags(const LOKI_SAFEFORMAT_UNSIGNED_LONG i) {
+ // look at the format character
+ Char formatChar = *format_;
+ bool isSigned = formatChar == 'd' || formatChar == 'i';
+ if (formatChar == 'p') {
+ formatChar = 'x'; // pointers go to hex
+ SetAlternateForm(); // printed with '0x' in front
+ isSigned = true; // that's what gcc does
+ }
+ if (!strchr("cdiuoxX", formatChar)) {
+ result_ = -1;
+ return;
+ }
+ Char buf[
+ sizeof(LOKI_SAFEFORMAT_UNSIGNED_LONG) * 3 // digits
+ + 1 // sign or ' '
+ + 2 // 0x or 0X
+ + 1]; // terminating zero
+ const Char *const bufEnd = buf + (sizeof(buf) / sizeof(Char));
+ Char * bufLast = buf + (sizeof(buf) / sizeof(Char) - 1);
+ Char signChar = 0;
+ unsigned int base = 10;
+
+ if (formatChar == 'c') {
+ // Format only one character
+ // The 'fill with zeros' flag is ignored
+ ResetFillZeros();
+ *bufLast = static_cast<char>(i);
+ } else {
+ // TODO: inefficient code, refactor
+ const bool negative = isSigned && static_cast<LOKI_SAFEFORMAT_SIGNED_LONG>(i) < 0;
+ if (formatChar == 'o') base = 8;
+ else if (formatChar == 'x' || formatChar == 'X') base = 16;
+ bufLast = isSigned
+ ? RenderWithoutSign(static_cast<LOKI_SAFEFORMAT_SIGNED_LONG>(i), bufLast, base,
+ formatChar == 'X')
+ : RenderWithoutSign(i, bufLast, base,
+ formatChar == 'X');
+ // Add the sign
+ if (isSigned) {
+ negative ? signChar = '-'
+ : ShowSignAlways() ? signChar = '+'
+ : Blank() ? signChar = ' '
+ : 0;
+ }
+ }
+ // precision
+ size_t
+ countDigits = bufEnd - bufLast,
+ countZeros = prec_ != size_t(-1) && countDigits < prec_ &&
+ formatChar != 'c'
+ ? prec_ - countDigits
+ : 0,
+ countBase = base != 10 && AlternateForm() && i != 0
+ ? (base == 16 ? 2 : countZeros > 0 ? 0 : 1)
+ : 0,
+ countSign = (signChar != 0),
+ totalPrintable = countDigits + countZeros + countBase + countSign;
+ size_t countPadLeft = 0, countPadRight = 0;
+ if (width_ > totalPrintable) {
+ if (LeftJustify()) {
+ countPadRight = width_ - totalPrintable;
+ countPadLeft = 0;
+ } else {
+ countPadLeft = width_ - totalPrintable;
+ countPadRight = 0;
+ }
+ }
+ if (FillZeros() && prec_ == size_t(-1)) {
+ // pad with zeros and no precision - transfer padding to precision
+ countZeros = countPadLeft;
+ countPadLeft = 0;
+ }
+ // ok, all computed, ready to print to device
+ Fill(' ', countPadLeft);
+ if (signChar != 0) Write(&signChar, &signChar + 1);
+ if (countBase > 0) Fill('0', 1);
+ if (countBase == 2) Fill(formatChar, 1);
+ Fill('0', countZeros);
+ Write(bufLast, bufEnd);
+ Fill(' ', countPadRight);
+ // done, advance
+ Next();
+ }
+
+ void Write(const Char* b, const Char* e) {
+ if (result_ < 0) return;
+ const LOKI_SAFEFORMAT_SIGNED_LONG x = e - b;
+ write(device_, b, e);
+ result_ += x;
+ }
+
+ template <class Value>
+ void PrintUsing_snprintf(Value n, const char* check_fmt_char) {
+ const Char *const fmt = format_ - 1;
+ assert(*fmt == '%');
+ // enforce format string validity
+ ReadLeaders();
+ // enforce format spec
+ if (!strchr(check_fmt_char, *format_)) {
+ result_ = -1;
+ return;
+ }
+ // format char validated, copy it to a temp and use legacy sprintf
+ ++format_;
+ Char fmtBuf[128], resultBuf[1024];
+ if (format_ >= fmt + sizeof(fmtBuf) / sizeof(Char)) {
+ result_ = -1;
+ return;
+ }
+ memcpy(fmtBuf, fmt, (format_ - fmt) * sizeof(Char));
+ fmtBuf[format_ - fmt] = 0;
+
+ const int stored =
+#ifdef _MSC_VER
+#if _MSC_VER < 1400
+ _snprintf
+#else
+ _snprintf_s
+#endif
+#else
+ snprintf
+#endif
+ (resultBuf, sizeof(resultBuf) / sizeof(Char), fmtBuf, n);
+
+ if (stored < 0) {
+ result_ = -1;
+ return;
+ }
+ Write(resultBuf, resultBuf + strlen(resultBuf));
+ Advance(); // output stuff to the next format directive
+ }
+
+ void Fill(const Char c, size_t n) {
+ for (; n > 0; --n) {
+ Write(&c, &c + 1);
+ }
+ }
+
+ Char* RenderWithoutSign(LOKI_SAFEFORMAT_UNSIGNED_LONG n, char* bufLast,
+ unsigned int base, bool uppercase) {
+ const Char hex1st = uppercase ? 'A' : 'a';
+ for (;;) {
+ const LOKI_SAFEFORMAT_UNSIGNED_LONG next = n / base;
+ Char c = static_cast<Char>(n - next * base);
+ c = static_cast<Char>(c + (c <= 9 ? '0' : static_cast<Char>(hex1st - 10)));
+ *bufLast = c;
+ n = next;
+ if (n == 0) break;
+ --bufLast;
+ }
+ return bufLast;
+ }
+
+ char* RenderWithoutSign(LOKI_SAFEFORMAT_SIGNED_LONG n, char* bufLast, unsigned int base,
+ bool uppercase) {
+ if (n != LONG_MIN) {
+ return RenderWithoutSign(static_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(n < 0 ? -n : n),
+ bufLast, base, uppercase);
+ }
+ // annoying corner case
+ char* save = bufLast;
+ ++n;
+ bufLast = RenderWithoutSign(static_cast<LOKI_SAFEFORMAT_UNSIGNED_LONG>(n),
+ bufLast, base, uppercase);
+ --(*save);
+ return bufLast;
+ }
+
+ void Next() {
+ ++format_;
+ Advance();
+ }
+
+ void Advance() {
+ ResetAll();
+ const Char* begin = format_;
+ for (;;) {
+ if (*format_ == '%') {
+ if (format_[1] != '%') { // It's a format specifier
+ Write(begin, format_);
+ ++format_;
+ break;
+ }
+ // It's a "%%"
+ Write(begin, ++format_);
+ begin = ++format_;
+ continue;
+ }
+ if (*format_ == 0) {
+ Write(begin, format_);
+ break;
+ }
+ ++format_;
+ }
+ }
+
+ void ReadFlags() {
+ for (;; ++format_) {
+ switch (*format_) {
+ case '-': SetLeftJustify(); break;
+ case '+': SetShowSignAlways(); break;
+ case ' ': SetBlank(); break;
+ case '#': SetAlternateForm(); break;
+ case '0': SetFillZeros(); break;
+ default: return;
+ }
+ }
+ }
+
+ void ParseDecimalSizeT(size_t& dest) {
+ if (!std::isdigit(*format_, std::locale())) return;
+ size_t r = 0;
+ do {
+ // TODO: inefficient - rewrite
+ r *= 10;
+ r += *format_ - '0';
+ ++format_;
+ } while (std::isdigit(*format_, std::locale()));
+ dest = r;
+ }
+
+ void ReadWidth() {
+ ParseDecimalSizeT(width_);
+ }
+
+ void ReadPrecision() {
+ assert(*format_ == '.');
+ ++format_;
+ ParseDecimalSizeT(prec_);
+ }
+
+ void ReadModifiers() {
+ switch (*format_) {
+ case 'h': SetForceShort(); ++format_; break;
+ case 'l': ++format_; break;
+ // more (C99 and platform-specific modifiers) to come
+ }
+ }
+
+ void ReadLeaders() {
+ ReadFlags();
+ ReadWidth();
+ if (*format_ == '.') ReadPrecision();
+ ReadModifiers();
+ }
+
+ enum {
+ leftJustify = 1,
+ showSignAlways = 2,
+ blank = 4,
+ alternateForm = 8,
+ fillZeros = 16,
+ forceShort = 32
+ };
+
+ bool LeftJustify() const { return (flags_ & leftJustify) != 0; }
+ bool ShowSignAlways() const { return (flags_ & showSignAlways) != 0; }
+ void SetWidth(size_t w) { width_ = w; }
+ void SetLeftJustify() { flags_ |= leftJustify; }
+ void SetShowSignAlways() { flags_ |= showSignAlways; }
+ bool Blank() const { return (flags_ & blank) != 0; }
+ bool AlternateForm() const { return (flags_ & alternateForm) != 0; }
+ bool FillZeros() const { return (flags_ & fillZeros) != 0; }
+ bool ForceShort() const { return (flags_ & forceShort) != 0; }
+
+ void SetPrec(size_t p) { prec_ = p; }
+ void SetBlank() { flags_ |= blank; }
+ void SetAlternateForm() { flags_ |= alternateForm; }
+ void SetFillZeros() { flags_ |= fillZeros; }
+ void ResetFillZeros() { flags_ &= ~fillZeros; }
+ void SetForceShort() { flags_ |= forceShort; }
+
+ void ResetAll() {
+ assert(result_ != EOF);
+ width_ = 0;
+ prec_ = size_t(-1);
+ flags_ = 0;
+ }
+
+ // state
+ Device device_;
+ const Char* format_;
+ size_t width_;
+ size_t prec_;
+ unsigned int flags_;
+ LOKI_SAFEFORMAT_SIGNED_LONG result_;
+ };
+
+ LOKI_EXPORT
+ PrintfState<std::FILE*, char> Printf(const char* format);
+
+ LOKI_EXPORT
+ PrintfState<std::FILE*, char> Printf(const std::string& format);
+
+ LOKI_EXPORT
+ PrintfState<std::FILE*, char> FPrintf(std::FILE* f, const char* format);
+
+ LOKI_EXPORT
+ PrintfState<std::FILE*, char> FPrintf(std::FILE* f, const std::string& format);
+
+ LOKI_EXPORT
+ PrintfState<std::ostream&, char> FPrintf(std::ostream& f, const char* format);
+
+ LOKI_EXPORT
+ PrintfState<std::ostream&, char> FPrintf(std::ostream& f, const std::string& format);
+
+ LOKI_EXPORT
+ PrintfState<std::string&, char> SPrintf(std::string& s, const char* format);
+
+ LOKI_EXPORT
+ PrintfState<std::string&, char> SPrintf(std::string& s, const std::string& format);
+
+ template <class T, class Char>
+ PrintfState<T&, Char> XPrintf(T& device, const Char* format) {
+ return PrintfState<T&, Char>(device, format);
+ }
+
+ template <class T>
+ PrintfState<T&, char> XPrintf(T& device, const std::string& format) {
+ return PrintfState<T&, char>(device, format.c_str());
+ }
+
+ template <class Char, std::size_t N>
+ PrintfState<std::pair<Char*, std::size_t>, Char>
+ BufPrintf(Char (&buf)[N], const Char* format) {
+ std::pair<Char*, std::size_t> temp(buf, N);
+ return PrintfState<std::pair<Char*, std::size_t>, Char>(temp, format);
+ }
+
+}// namespace Loki
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/ScopeGuard.h b/shared/loki/ScopeGuard.h
new file mode 100644
index 00000000..a7e61ddd
--- /dev/null
+++ b/shared/loki/ScopeGuard.h
@@ -0,0 +1,666 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2000 Andrei Alexandrescu
+// Copyright (c) 2000 Petru Marginean
+// Copyright (c) 2005 Joshua Lehrer
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_SCOPEGUARD_INC_
+#define LOKI_SCOPEGUARD_INC_
+
+// $Id: ScopeGuard.h 799 2006-12-20 00:37:13Z rich_sposato $
+
+
+#include <loki/RefToValue.h>
+
+/// \defgroup ExceptionGroup Exception-safe code
+
+namespace Loki
+{
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ScopeGuardImplBase
+ /// \ingroup ExceptionGroup
+ ///
+ /// Base class used by all ScopeGuard implementations. All commonly used
+ /// functions are in this class (e.g. - Dismiss and SafeExecute).
+ ///
+ /// See Andrei's and Petru Marginean's CUJ article
+ /// http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm
+ ///
+ /// Changes to the original code by Joshua Lehrer:
+ /// http://www.lehrerfamily.com/scopeguard.html
+ ////////////////////////////////////////////////////////////////
+
+ class ScopeGuardImplBase
+ {
+ /// Copy-assignment operator is not implemented and private.
+ ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
+
+ protected:
+
+ ~ScopeGuardImplBase()
+ {}
+
+ /// Copy-constructor takes over responsibility from other ScopeGuard.
+ ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
+ : dismissed_(other.dismissed_)
+ {
+ other.Dismiss();
+ }
+
+ template <typename J>
+ static void SafeExecute(J& j) throw()
+ {
+ if (!j.dismissed_)
+ try
+ {
+ j.Execute();
+ }
+ catch(...)
+ {}
+ }
+
+ mutable bool dismissed_;
+
+ public:
+ ScopeGuardImplBase() throw() : dismissed_(false)
+ {}
+
+ void Dismiss() const throw()
+ {
+ dismissed_ = true;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \typedef typedef const ScopeGuardImplBase& ScopeGuard
+ /// \ingroup ExceptionGroup
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ typedef const ScopeGuardImplBase& ScopeGuard;
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ScopeGuardImpl0
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a standalone function or class static function
+ /// with no parameters. ScopeGuard ignores any value returned from the
+ /// call within the Execute function.
+ ///
+ /// This class has a single standalone helper function, MakeGuard which
+ /// creates and returns a ScopeGuard.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template <typename F>
+ class ScopeGuardImpl0 : public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl0<F> MakeGuard(F fun)
+ {
+ return ScopeGuardImpl0<F>(fun);
+ }
+
+ ~ScopeGuardImpl0() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ fun_();
+ }
+
+ protected:
+ ScopeGuardImpl0(F fun) : fun_(fun)
+ {}
+
+ F fun_;
+ };
+
+ template <typename F>
+ inline ScopeGuardImpl0<F> MakeGuard(F fun)
+ {
+ return ScopeGuardImpl0<F>::MakeGuard(fun);
+ }
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ScopeGuardImpl1
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a standalone function or class static function
+ /// with one parameter. Each parameter is copied by value - use
+ /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
+ /// any value returned from the call within the Execute function.
+ ///
+ /// This class has a single standalone helper function, MakeGuard which
+ /// creates and returns a ScopeGuard.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template <typename F, typename P1>
+ class ScopeGuardImpl1 : public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
+ {
+ return ScopeGuardImpl1<F, P1>(fun, p1);
+ }
+
+ ~ScopeGuardImpl1() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ fun_(p1_);
+ }
+
+ protected:
+ ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
+ {}
+
+ F fun_;
+ const P1 p1_;
+ };
+
+ template <typename F, typename P1>
+ inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
+ {
+ return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
+ }
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ScopeGuardImpl2
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a standalone function or class static function
+ /// with two parameters. Each parameter is copied by value - use
+ /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
+ /// any value returned from the call within the Execute function.
+ ///
+ /// This class has a single standalone helper function, MakeGuard which
+ /// creates and returns a ScopeGuard.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template <typename F, typename P1, typename P2>
+ class ScopeGuardImpl2: public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
+ {
+ return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
+ }
+
+ ~ScopeGuardImpl2() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ fun_(p1_, p2_);
+ }
+
+ protected:
+ ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2)
+ {}
+
+ F fun_;
+ const P1 p1_;
+ const P2 p2_;
+ };
+
+ template <typename F, typename P1, typename P2>
+ inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
+ {
+ return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
+ }
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ScopeGuardImpl3
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a standalone function or class static function
+ /// with three parameters. Each parameter is copied by value - use
+ /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
+ /// any value returned from the call within the Execute function.
+ ///
+ /// This class has a single standalone helper function, MakeGuard which
+ /// creates and returns a ScopeGuard.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template <typename F, typename P1, typename P2, typename P3>
+ class ScopeGuardImpl3 : public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
+ {
+ return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
+ }
+
+ ~ScopeGuardImpl3() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ fun_(p1_, p2_, p3_);
+ }
+
+ protected:
+ ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3)
+ {}
+
+ F fun_;
+ const P1 p1_;
+ const P2 p2_;
+ const P3 p3_;
+ };
+
+ template <typename F, typename P1, typename P2, typename P3>
+ inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
+ {
+ return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
+ }
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ScopeGuardImpl4
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a standalone function or class static function
+ /// with four parameters. Each parameter is copied by value - use
+ /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
+ /// any value returned from the call within the Execute function.
+ ///
+ /// This class has a single standalone helper function, MakeGuard which
+ /// creates and returns a ScopeGuard.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template < typename F, typename P1, typename P2, typename P3, typename P4 >
+ class ScopeGuardImpl4 : public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard(
+ F fun, P1 p1, P2 p2, P3 p3, P4 p4 )
+ {
+ return ScopeGuardImpl4< F, P1, P2, P3, P4 >( fun, p1, p2, p3, p4 );
+ }
+
+ ~ScopeGuardImpl4() throw()
+ {
+ SafeExecute( *this );
+ }
+
+ void Execute()
+ {
+ fun_( p1_, p2_, p3_, p4_ );
+ }
+
+ protected:
+ ScopeGuardImpl4( F fun, P1 p1, P2 p2, P3 p3, P4 p4 ) :
+ fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 )
+ {}
+
+ F fun_;
+ const P1 p1_;
+ const P2 p2_;
+ const P3 p3_;
+ const P4 p4_;
+ };
+
+ template < typename F, typename P1, typename P2, typename P3, typename P4 >
+ inline ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4 )
+ {
+ return ScopeGuardImpl4< F, P1, P2, P3, P4 >::MakeGuard( fun, p1, p2, p3, p4 );
+ }
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ScopeGuardImpl5
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a standalone function or class static function
+ /// with five parameters. Each parameter is copied by value - use
+ /// ::Loki::ByRef if you must use a reference instead. ScopeGuard ignores
+ /// any value returned from the call within the Execute function.
+ ///
+ /// This class has a single standalone helper function, MakeGuard which
+ /// creates and returns a ScopeGuard.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 >
+ class ScopeGuardImpl5 : public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard(
+ F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 )
+ {
+ return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >( fun, p1, p2, p3, p4, p5 );
+ }
+
+ ~ScopeGuardImpl5() throw()
+ {
+ SafeExecute( *this );
+ }
+
+ void Execute()
+ {
+ fun_( p1_, p2_, p3_, p4_, p5_ );
+ }
+
+ protected:
+ ScopeGuardImpl5( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) :
+ fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 ), p5_( p5 )
+ {}
+
+ F fun_;
+ const P1 p1_;
+ const P2 p2_;
+ const P3 p3_;
+ const P4 p4_;
+ const P5 p5_;
+ };
+
+ template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 >
+ inline ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 )
+ {
+ return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >::MakeGuard( fun, p1, p2, p3, p4, p5 );
+ }
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ObjScopeGuardImpl0
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a class per-instance member function with no
+ /// parameters. ScopeGuard ignores any value returned from the call within
+ /// the Execute function.
+ ///
+ /// This class has 3 standalone helper functions which create a ScopeGuard.
+ /// One is MakeObjGuard, which is deprecated but provided for older code.
+ /// The other two are MakeGuard overloads, one which takes a pointer to an
+ /// object, and the other which takes a reference.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template <class Obj, typename MemFun>
+ class ObjScopeGuardImpl0 : public ScopeGuardImplBase
+ {
+ public:
+ static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
+ {
+ return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
+ }
+
+ ~ObjScopeGuardImpl0() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ (obj_.*memFun_)();
+ }
+
+ protected:
+ ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun)
+ {}
+
+ Obj& obj_;
+ MemFun memFun_;
+ };
+
+ template <class Obj, typename MemFun>
+ inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
+ {
+ return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
+ }
+
+ template <typename Ret, class Obj1, class Obj2>
+ inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj)
+ {
+ return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(obj,memFun);
+ }
+
+ template <typename Ret, class Obj1, class Obj2>
+ inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj)
+ {
+ return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(*obj,memFun);
+ }
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ObjScopeGuardImpl1
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a class per-instance member function with one
+ /// parameter. The parameter is copied by value - use ::Loki::ByRef if you
+ /// must use a reference instead. ScopeGuard ignores any value returned
+ /// from the call within the Execute function.
+ ///
+ /// This class has 3 standalone helper functions which create a ScopeGuard.
+ /// One is MakeObjGuard, which is deprecated but provided for older code.
+ /// The other two are MakeGuard overloads, one which takes a pointer to an
+ /// object, and the other which takes a reference.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template <class Obj, typename MemFun, typename P1>
+ class ObjScopeGuardImpl1 : public ScopeGuardImplBase
+ {
+ public:
+ static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
+ {
+ return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
+ }
+
+ ~ObjScopeGuardImpl1() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ (obj_.*memFun_)(p1_);
+ }
+
+ protected:
+ ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1)
+ {}
+
+ Obj& obj_;
+ MemFun memFun_;
+ const P1 p1_;
+ };
+
+ template <class Obj, typename MemFun, typename P1>
+ inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
+ {
+ return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
+ }
+
+ template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
+ inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1)
+ {
+ return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(obj,memFun,p1);
+ }
+
+ template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
+ inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1)
+ {
+ return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1);
+ }
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ObjScopeGuardImpl2
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a class per-instance member function with two
+ /// parameters. Each parameter is copied by value - use ::Loki::ByRef if you
+ /// must use a reference instead. ScopeGuard ignores any value returned
+ /// from the call within the Execute function.
+ ///
+ /// This class has 3 standalone helper functions which create a ScopeGuard.
+ /// One is MakeObjGuard, which is deprecated but provided for older code.
+ /// The other two are MakeGuard overloads, one which takes a pointer to an
+ /// object, and the other which takes a reference.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template <class Obj, typename MemFun, typename P1, typename P2>
+ class ObjScopeGuardImpl2 : public ScopeGuardImplBase
+ {
+ public:
+ static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
+ {
+ return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
+ }
+
+ ~ObjScopeGuardImpl2() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ (obj_.*memFun_)(p1_, p2_);
+ }
+
+ protected:
+ ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2)
+ {}
+
+ Obj& obj_;
+ MemFun memFun_;
+ const P1 p1_;
+ const P2 p2_;
+ };
+
+ template <class Obj, typename MemFun, typename P1, typename P2>
+ inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
+ {
+ return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
+ }
+
+ template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
+ inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2)
+ {
+ return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2);
+ }
+
+ template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
+ inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2)
+ {
+ return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2);
+ }
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \class ObjScopeGuardImpl3
+ /// \ingroup ExceptionGroup
+ ///
+ /// Implementation class for a class per-instance member function with three
+ /// parameters. Each parameter is copied by value - use ::Loki::ByRef if you
+ /// must use a reference instead. ScopeGuard ignores any value returned
+ /// from the call within the Execute function.
+ ///
+ /// This class has 3 standalone helper functions which create a ScopeGuard.
+ /// One is MakeObjGuard, which is deprecated but provided for older code.
+ /// The other two are MakeGuard overloads, one which takes a pointer to an
+ /// object, and the other which takes a reference.
+ ///
+ ////////////////////////////////////////////////////////////////
+
+ template < class Obj, typename MemFun, typename P1, typename P2, typename P3 >
+ class ObjScopeGuardImpl3 : public ScopeGuardImplBase
+ {
+ public:
+ static ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard(
+ Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 )
+ {
+ return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >( obj, memFun, p1, p2, p3 );
+ }
+
+ ~ObjScopeGuardImpl3() throw()
+ {
+ SafeExecute( *this );
+ }
+
+ void Execute()
+ {
+ ( obj_.*memFun_ )( p1_, p2_, p3_ );
+ }
+
+ protected:
+ ObjScopeGuardImpl3( Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 ) :
+ obj_( obj ), memFun_( memFun ), p1_( p1 ), p2_( p2 ), p3_( p3 )
+ {}
+
+ Obj& obj_;
+ MemFun memFun_;
+ const P1 p1_;
+ const P2 p2_;
+ const P3 p3_;
+ };
+
+ template < class Obj, typename MemFun, typename P1, typename P2, typename P3 >
+ inline ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard(
+ Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 )
+ {
+ return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >::MakeObjGuard(
+ obj, memFun, p1, p2, p3 );
+ }
+
+ template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b,
+ typename P2a, typename P2b, typename P3a, typename P3b >
+ inline ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
+ MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 & obj, P1b p1, P2b p2, P3b p3 )
+ {
+ return ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
+ ::MakeObjGuard( obj, memFun, p1, p2, p3 );
+ }
+
+ template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b,
+ typename P2a, typename P2b, typename P3a, typename P3b >
+ inline ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
+ MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 * obj, P1b p1, P2b p2, P3b p3 )
+ {
+ return ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
+ ::MakeObjGuard( *obj, memFun, p1, p2, p3 );
+ }
+
+} // namespace Loki
+
+#define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2
+#define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2)
+#define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__)
+
+#define LOKI_ON_BLOCK_EXIT ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeGuard
+#define LOKI_ON_BLOCK_EXIT_OBJ ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeObjGuard
+
+#endif // end file guardian
+
diff --git a/shared/loki/Sequence.h b/shared/loki/Sequence.h
new file mode 100644
index 00000000..4e5bd235
--- /dev/null
+++ b/shared/loki/Sequence.h
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2005 by Peter Kümmel
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_SEQUENCE_INC_
+#define LOKI_SEQUENCE_INC_
+
+// $Id: Sequence.h 768 2006-10-25 20:40:40Z syntheticpp $
+
+
+#include "Typelist.h"
+
+namespace Loki
+{
+
+ template
+ <
+ class T01=NullType,class T02=NullType,class T03=NullType,class T04=NullType,class T05=NullType,
+ class T06=NullType,class T07=NullType,class T08=NullType,class T09=NullType,class T10=NullType,
+ class T11=NullType,class T12=NullType,class T13=NullType,class T14=NullType,class T15=NullType,
+ class T16=NullType,class T17=NullType,class T18=NullType,class T19=NullType,class T20=NullType
+ >
+ struct Seq
+ {
+ private:
+ typedef typename Seq< T02, T03, T04, T05, T06, T07, T08, T09, T10,
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>::Type
+ TailResult;
+ public:
+ typedef Typelist<T01, TailResult> Type;
+ };
+
+ template<>
+ struct Seq<>
+ {
+ typedef NullType Type;
+ };
+
+} // namespace Loki
+
+#endif // end file guardian
+
diff --git a/shared/loki/Singleton.h b/shared/loki/Singleton.h
new file mode 100644
index 00000000..42d6eb0d
--- /dev/null
+++ b/shared/loki/Singleton.h
@@ -0,0 +1,889 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_SINGLETON_INC_
+#define LOKI_SINGLETON_INC_
+
+// $Id: Singleton.h 834 2007-08-02 19:36:10Z syntheticpp $
+
+
+#include "LokiExport.h"
+#include "Threads.h"
+#include <algorithm>
+#include <stdexcept>
+#include <cassert>
+#include <cstdlib>
+#include <new>
+#include <vector>
+#include <list>
+#include <memory>
+
+#ifdef _MSC_VER
+#define LOKI_C_CALLING_CONVENTION_QUALIFIER __cdecl
+#else
+#define LOKI_C_CALLING_CONVENTION_QUALIFIER
+#endif
+
+/// \defgroup SingletonGroup Singleton
+/// \defgroup CreationGroup Creation policies
+/// \ingroup SingletonGroup
+/// \defgroup LifetimeGroup Lifetime policies
+/// \ingroup SingletonGroup
+/// The lifetimes of the singleton.
+/// \par Special lifetime for SmallObjects
+/// When the holded object is a Small(Value)Object or the holded object
+/// uses objects which are or inherit from Small(Value)Object
+/// then you can't use the default lifetime: you must use the lifetime
+/// \code Loki::LongevityLifetime::DieAsSmallObjectChild \endcode
+/// Be aware of this when you use Loki::Factory, Loki::Functor, or Loki::Function.
+
+
+
+namespace Loki
+{
+ typedef void (LOKI_C_CALLING_CONVENTION_QUALIFIER *atexit_pfn_t)();
+
+ namespace Private
+ {
+
+#ifndef LOKI_MAKE_DLL
+ void LOKI_C_CALLING_CONVENTION_QUALIFIER AtExitFn(); // declaration needed below
+#else
+ void LOKI_EXPORT AtExitFn();
+#endif
+
+ class LifetimeTracker;
+
+#define LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
+#ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
+
+ // Helper data
+ // std::list because of the inserts
+ typedef std::list<LifetimeTracker*> TrackerArray;
+ extern LOKI_EXPORT TrackerArray* pTrackerArray;
+#else
+ // Helper data
+ typedef LifetimeTracker** TrackerArray;
+ extern TrackerArray pTrackerArray;
+ extern unsigned int elements;
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // class LifetimeTracker
+ // Helper class for SetLongevity
+ ////////////////////////////////////////////////////////////////////////////////
+
+ class LifetimeTracker
+ {
+ public:
+ LifetimeTracker(unsigned int x) : longevity_(x)
+ {}
+
+ virtual ~LifetimeTracker() = 0;
+
+ static bool Compare(const LifetimeTracker* lhs,
+ const LifetimeTracker* rhs)
+ {
+ return lhs->longevity_ > rhs->longevity_;
+ }
+
+ private:
+ unsigned int longevity_;
+ };
+
+ // Definition required
+ inline LifetimeTracker::~LifetimeTracker() {}
+
+ // Helper destroyer function
+ template <typename T>
+ struct Deleter
+ {
+ typedef void (*Type)(T*);
+ static void Delete(T* pObj)
+ { delete pObj; }
+ };
+
+ // Concrete lifetime tracker for objects of type T
+ template <typename T, typename Destroyer>
+ class ConcreteLifetimeTracker : public LifetimeTracker
+ {
+ public:
+ ConcreteLifetimeTracker(T* p,unsigned int longevity, Destroyer d)
+ : LifetimeTracker(longevity)
+ , pTracked_(p)
+ , destroyer_(d)
+ {}
+
+ ~ConcreteLifetimeTracker()
+ { destroyer_(pTracked_); }
+
+ private:
+ T* pTracked_;
+ Destroyer destroyer_;
+ };
+
+ } // namespace Private
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \ingroup LifetimeGroup
+ ///
+ /// Assigns an object a longevity; ensures ordered destructions of objects
+ /// registered thusly during the exit sequence of the application
+ ////////////////////////////////////////////////////////////////////////////////
+
+#ifdef LOKI_ENABLE_NEW_SETLONGLIVITY_HELPER_DATA_IMPL
+
+ template <typename T, typename Destroyer>
+ void SetLongevity(T* pDynObject, unsigned int longevity,
+ Destroyer d)
+ {
+ using namespace Private;
+
+ // manage lifetime of stack manually
+ if(pTrackerArray==0)
+ pTrackerArray = new TrackerArray;
+
+ // automatically delete the ConcreteLifetimeTracker object when a exception is thrown
+ std::auto_ptr<LifetimeTracker>
+ p( new ConcreteLifetimeTracker<T, Destroyer>(pDynObject, longevity, d) );
+
+ // Find correct position
+ TrackerArray::iterator pos = std::upper_bound(
+ pTrackerArray->begin(),
+ pTrackerArray->end(),
+ p.get(),
+ LifetimeTracker::Compare);
+
+ // Insert the pointer to the ConcreteLifetimeTracker object into the queue
+ pTrackerArray->insert(pos, p.get());
+
+ // nothing has thrown: don't delete the ConcreteLifetimeTracker object
+ p.release();
+
+ // Register a call to AtExitFn
+ std::atexit(Private::AtExitFn);
+ }
+
+#else
+
+ template <typename T, typename Destroyer>
+ void SetLongevity(T* pDynObject, unsigned int longevity,
+ Destroyer d)
+ {
+ using namespace Private;
+
+ TrackerArray pNewArray = static_cast<TrackerArray>(
+ std::realloc(pTrackerArray,
+ sizeof(*pTrackerArray) * (elements + 1)));
+ if (!pNewArray) throw std::bad_alloc();
+
+ // Delayed assignment for exception safety
+ pTrackerArray = pNewArray;
+
+ LifetimeTracker* p = new ConcreteLifetimeTracker<T, Destroyer>(
+ pDynObject, longevity, d);
+
+ // Insert a pointer to the object into the queue
+ TrackerArray pos = std::upper_bound(
+ pTrackerArray,
+ pTrackerArray + elements,
+ p,
+ LifetimeTracker::Compare);
+ std::copy_backward(
+ pos,
+ pTrackerArray + elements,
+ pTrackerArray + elements + 1);
+ *pos = p;
+ ++elements;
+
+ // Register a call to AtExitFn
+ std::atexit(Private::AtExitFn);
+ }
+
+#endif
+
+ template <typename T>
+ void SetLongevity(T* pDynObject, unsigned int longevity,
+ typename Private::Deleter<T>::Type d = Private::Deleter<T>::Delete)
+ {
+ SetLongevity<T, typename Private::Deleter<T>::Type>(pDynObject, longevity, d);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct CreateUsingNew
+ ///
+ /// \ingroup CreationGroup
+ /// Implementation of the CreationPolicy used by SingletonHolder
+ /// Creates objects using a straight call to the new operator
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class T> struct CreateUsingNew
+ {
+ static T* Create()
+ { return new T; }
+
+ static void Destroy(T* p)
+ { delete p; }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct CreateUsing
+ ///
+ /// \ingroup CreationGroup
+ /// Implementation of the CreationPolicy used by SingletonHolder
+ /// Creates objects using a custom allocater.
+ /// Usage: e.g. CreateUsing<std::allocator>::Allocator
+ ////////////////////////////////////////////////////////////////////////////////
+ template<template<class> class Alloc>
+ struct CreateUsing
+ {
+ template <class T>
+ struct Allocator
+ {
+ static Alloc<T> allocator;
+
+ static T* Create()
+ {
+ return new (allocator.allocate(1)) T;
+ }
+
+ static void Destroy(T* p)
+ {
+ //allocator.destroy(p);
+ p->~T();
+ allocator.deallocate(p,1);
+ }
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct CreateUsingMalloc
+ ///
+ /// \ingroup CreationGroup
+ /// Implementation of the CreationPolicy used by SingletonHolder
+ /// Creates objects using a call to std::malloc, followed by a call to the
+ /// placement new operator
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class T> struct CreateUsingMalloc
+ {
+ static T* Create()
+ {
+ void* p = std::malloc(sizeof(T));
+ if (!p) return 0;
+ return new(p) T;
+ }
+
+ static void Destroy(T* p)
+ {
+ p->~T();
+ std::free(p);
+ }
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct CreateStatic
+ ///
+ /// \ingroup CreationGroup
+ /// Implementation of the CreationPolicy used by SingletonHolder
+ /// Creates an object in static memory
+ /// Implementation is slightly nonportable because it uses the MaxAlign trick
+ /// (an union of all types to ensure proper memory alignment). This trick is
+ /// nonportable in theory but highly portable in practice.
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class T> struct CreateStatic
+ {
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4121 )
+// alignment of a member was sensitive to packing
+#endif // _MSC_VER
+
+ union MaxAlign
+ {
+ char t_[sizeof(T)];
+ short int shortInt_;
+ int int_;
+ long int longInt_;
+ float float_;
+ double double_;
+ long double longDouble_;
+ struct Test;
+ int Test::* pMember_;
+ int (Test::*pMemberFn_)(int);
+ };
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif // _MSC_VER
+
+ static T* Create()
+ {
+ static MaxAlign staticMemory_;
+ return new(&staticMemory_) T;
+ }
+
+ static void Destroy(T* p)
+ {
+ p->~T();
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct DefaultLifetime
+ ///
+ /// \ingroup LifetimeGroup
+ /// Implementation of the LifetimePolicy used by SingletonHolder
+ /// Schedules an object's destruction as per C++ rules
+ /// Forwards to std::atexit
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class T>
+ struct DefaultLifetime
+ {
+ static void ScheduleDestruction(T*, atexit_pfn_t pFun)
+ { std::atexit(pFun); }
+
+ static void OnDeadReference()
+ { throw std::logic_error("Dead Reference Detected"); }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct PhoenixSingleton
+ ///
+ /// \ingroup LifetimeGroup
+ /// Implementation of the LifetimePolicy used by SingletonHolder
+ /// Schedules an object's destruction as per C++ rules, and it allows object
+ /// recreation by not throwing an exception from OnDeadReference
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class T>
+ class PhoenixSingleton
+ {
+ public:
+ static void ScheduleDestruction(T*, atexit_pfn_t pFun)
+ {
+#ifndef ATEXIT_FIXED
+ if (!destroyedOnce_)
+#endif
+ std::atexit(pFun);
+ }
+
+ static void OnDeadReference()
+ {
+#ifndef ATEXIT_FIXED
+ destroyedOnce_ = true;
+#endif
+ }
+
+ private:
+#ifndef ATEXIT_FIXED
+ static bool destroyedOnce_;
+#endif
+ };
+
+#ifndef ATEXIT_FIXED
+ template <class T> bool PhoenixSingleton<T>::destroyedOnce_ = false;
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Copyright (c) 2004 by Curtis Krauskopf - curtis@decompile.com
+ ///
+ /// \struct DeletableSingleton
+ ///
+ /// \ingroup LifetimeGroup
+ ///
+ /// A DeletableSingleton allows the instantiated singleton to be
+ /// destroyed at any time. The singleton can be reinstantiated at
+ /// any time, even during program termination.
+ /// If the singleton exists when the program terminates, it will
+ /// be automatically deleted.
+ ///
+ /// \par Usage:
+ /// The singleton can be deleted manually:
+ ///
+ /// DeletableSingleton<MyClass>::GracefulDelete();
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class T>
+ class DeletableSingleton
+ {
+ public:
+
+ static void ScheduleDestruction(T*, atexit_pfn_t pFun)
+ {
+ static bool firstPass = true;
+ isDead = false;
+ deleter = pFun;
+ if (firstPass || needCallback)
+ {
+ std::atexit(atexitCallback);
+ firstPass = false;
+ needCallback = false;
+ }
+ }
+
+ static void OnDeadReference()
+ {
+ }
+ /// delete singleton object manually
+ static void GracefulDelete()
+ {
+ if (isDead)
+ return;
+ isDead = true;
+ deleter();
+ }
+
+ protected:
+ static atexit_pfn_t deleter;
+ static bool isDead;
+ static bool needCallback;
+
+ static void atexitCallback()
+ {
+#ifdef ATEXIT_FIXED
+ needCallback = true;
+#else
+ needCallback = false;
+#endif
+ GracefulDelete();
+ }
+ };
+
+ template <class T>
+ atexit_pfn_t DeletableSingleton<T>::deleter = 0;
+
+ template <class T>
+ bool DeletableSingleton<T>::isDead = true;
+
+ template <class T>
+ bool DeletableSingleton<T>::needCallback = true;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // class template Adapter
+ // Helper for SingletonWithLongevity below
+ ////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ template <class T>
+ struct Adapter
+ {
+ void operator()(T*) { return pFun_(); }
+ atexit_pfn_t pFun_;
+ };
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct SingletonWithLongevity
+ ///
+ /// \ingroup LifetimeGroup
+ /// Implementation of the LifetimePolicy used by SingletonHolder
+ /// Schedules an object's destruction in order of their longevities
+ /// Assumes a visible function GetLongevity(T*) that returns the longevity of the
+ /// object.
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class T>
+ class SingletonWithLongevity
+ {
+ public:
+ static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun)
+ {
+ Private::Adapter<T> adapter = { pFun };
+ SetLongevity(pObj, GetLongevity(pObj), adapter);
+ }
+
+ static void OnDeadReference()
+ { throw std::logic_error("Dead Reference Detected"); }
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct NoDestroy
+ ///
+ /// \ingroup LifetimeGroup
+ /// Implementation of the LifetimePolicy used by SingletonHolder
+ /// Never destroys the object
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class T>
+ struct NoDestroy
+ {
+ static void ScheduleDestruction(T*, atexit_pfn_t)
+ {}
+
+ static void OnDeadReference()
+ {}
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \defgroup LongevityLifetimeGroup LongevityLifetime
+ /// \ingroup LifetimeGroup
+ ///
+ /// \namespace LongevityLifetime
+ ///
+ /// \ingroup LongevityLifetimeGroup
+ /// \brief In this namespace are special lifetime policies to manage lifetime
+ /// dependencies.
+ ////////////////////////////////////////////////////////////////////////////////
+ namespace LongevityLifetime
+ {
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \struct SingletonFixedLongevity
+ ///
+ /// \ingroup LongevityLifetimeGroup
+ /// Add your own lifetimes into the namespace 'LongevityLifetime'
+ /// with your prefered lifetime by adding a struct like this:
+ ///
+ /// template<class T>
+ /// struct MyLifetime : SingletonFixedLongevity< MyLifetimeNumber ,T> {}
+ ////////////////////////////////////////////////////////////////////////////////
+ template <unsigned int Longevity, class T>
+ class SingletonFixedLongevity
+ {
+ public:
+ virtual ~SingletonFixedLongevity() {}
+
+ static void ScheduleDestruction(T* pObj, atexit_pfn_t pFun)
+ {
+ Private::Adapter<T> adapter = { pFun };
+ SetLongevity(pObj, Longevity , adapter);
+ }
+
+ static void OnDeadReference()
+ { throw std::logic_error("Dead Reference Detected"); }
+ };
+
+ /// \struct DieLast
+ /// \ingroup LongevityLifetimeGroup
+ /// \brief Longest possible SingletonWithLongevity lifetime: 0xFFFFFFFF
+ template <class T>
+ struct DieLast : SingletonFixedLongevity<0xFFFFFFFF ,T>
+ {};
+
+ /// \struct DieDirectlyBeforeLast
+ /// \ingroup LongevityLifetimeGroup
+ /// \brief Lifetime is a one less than DieLast: 0xFFFFFFFF-1
+ template <class T>
+ struct DieDirectlyBeforeLast : SingletonFixedLongevity<0xFFFFFFFF-1 ,T>
+ {};
+
+ /// \struct DieFirst
+ /// \ingroup LongevityLifetimeGroup
+ /// \brief Shortest possible SingletonWithLongevity lifetime: 0
+ template <class T>
+ struct DieFirst : SingletonFixedLongevity<0,T>
+ {};
+
+ }//namespace LongevityLifetime
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class FollowIntoDeath
+ ///
+ /// \ingroup LifetimeGroup
+ ///
+ /// Lifetime policyfor the SingletonHolder tempalte.
+ /// Followers will die after the master dies Followers will not die, if
+ /// - master never dies (NoDestroy policy)
+ /// - master never created
+ /// - master dies not in the function registered with atexit
+ /// - master dies not by a call of a the atexit registerd function (DeletableSingleton::GracefulDelete)
+ ///
+ /// \par Usage:
+ ///
+ /// Lifetimes of the master and the follower singletons, e.g. with a M and a F class:
+ /// \code SingletonHolder< M , FollowIntoDeath::With<DefaultLifetime>::AsMasterLifetime > MasterSingleton; \endcode
+ /// \code SingletonHolder< F , CreateUsingNew, FollowIntoDeath::AfterMaster< MasterSingleton >::IsDestroyed > FollowerSingleton \endcode
+ ////////////////////////////////////////////////////////////////////////////////
+ class FollowIntoDeath
+ {
+ template<class T>
+ class Followers
+ {
+ typedef std::vector<atexit_pfn_t> Container;
+ typedef typename Container::iterator iterator;
+ static Container* followers_;
+
+ public:
+ static void Init()
+ {
+ static bool done = false;
+ if(!done)
+ {
+ followers_ = new Container;
+ done = true;
+ }
+ }
+
+ static void AddFollower(atexit_pfn_t ae)
+ {
+ Init();
+ followers_->push_back(ae);
+ }
+
+ static void DestroyFollowers()
+ {
+ Init();
+ for(iterator it = followers_->begin();it != followers_->end();++it)
+ (*it)();
+ delete followers_;
+ }
+ };
+
+ public:
+
+ /// \struct With
+ /// Template for the master
+ /// \param Lifetime Lifetime policy for the master
+ template<template <class> class Lifetime>
+ struct With
+ {
+ /// \struct AsMasterLifetime
+ /// Policy for master
+ template<class Master>
+ struct AsMasterLifetime
+ {
+ static void ScheduleDestruction(Master* pObj, atexit_pfn_t pFun)
+ {
+ Followers<Master>::Init();
+ Lifetime<Master>::ScheduleDestruction(pObj, pFun);
+
+ // use same policy for the followers and force a new
+ // template instantiation, this adds a additional atexit entry
+ // does not work with SetLonlevity, but there you can control
+ // the lifetime with the GetLongevity function.
+ Lifetime<Followers<Master> >::ScheduleDestruction(0,Followers<Master>::DestroyFollowers);
+ }
+
+ static void OnDeadReference()
+ {
+ throw std::logic_error("Dead Reference Detected");
+ }
+ };
+ };
+
+ /// \struct AfterMaster
+ /// Template for the follower
+ /// \param Master Master to follow into death
+ template<class Master>
+ struct AfterMaster
+ {
+ /// \struct IsDestroyed
+ /// Policy for followers
+ template<class F>
+ struct IsDestroyed
+ {
+ static void ScheduleDestruction(F*, atexit_pfn_t pFun)
+ {
+ Followers<Master>::AddFollower(pFun);
+ }
+
+ static void OnDeadReference()
+ {
+ throw std::logic_error("Dead Reference Detected");
+ }
+ };
+ };
+ };
+
+ template<class T>
+ typename FollowIntoDeath::Followers<T>::Container*
+ FollowIntoDeath::Followers<T>::followers_ = 0;
+
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class SingletonHolder
+ ///
+ /// \ingroup SingletonGroup
+ ///
+ /// Provides Singleton amenities for a type T
+ /// To protect that type from spurious instantiations,
+ /// you have to protect it yourself.
+ ///
+ /// \param CreationPolicy Creation policy, default: CreateUsingNew
+ /// \param LifetimePolicy Lifetime policy, default: DefaultLifetime,
+ /// \param ThreadingModel Threading policy,
+ /// default: LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL
+ ////////////////////////////////////////////////////////////////////////////////
+ template
+ <
+ typename T,
+ template <class> class CreationPolicy = CreateUsingNew,
+ template <class> class LifetimePolicy = DefaultLifetime,
+ template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
+ class MutexPolicy = LOKI_DEFAULT_MUTEX
+ >
+ class SingletonHolder
+ {
+ public:
+
+ /// Type of the singleton object
+ typedef T ObjectType;
+
+ /// Returns a reference to singleton object
+ static T& Instance();
+
+ private:
+ // Helpers
+ static void MakeInstance();
+ static void LOKI_C_CALLING_CONVENTION_QUALIFIER DestroySingleton();
+
+ // Protection
+ SingletonHolder();
+
+ // Data
+ typedef typename ThreadingModel<T*,MutexPolicy>::VolatileType PtrInstanceType;
+ static PtrInstanceType pInstance_;
+ static bool destroyed_;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // SingletonHolder's data
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ class T,
+ template <class> class C,
+ template <class> class L,
+ template <class, class> class M,
+ class X
+ >
+ typename SingletonHolder<T, C, L, M, X>::PtrInstanceType
+ SingletonHolder<T, C, L, M, X>::pInstance_ = 0;
+
+ template
+ <
+ class T,
+ template <class> class C,
+ template <class> class L,
+ template <class, class> class M,
+ class X
+ >
+ bool SingletonHolder<T, C, L, M, X>::destroyed_ = false;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // SingletonHolder::Instance
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ class T,
+ template <class> class CreationPolicy,
+ template <class> class LifetimePolicy,
+ template <class, class> class ThreadingModel,
+ class MutexPolicy
+ >
+ inline T& SingletonHolder<T, CreationPolicy,
+ LifetimePolicy, ThreadingModel, MutexPolicy>::Instance()
+ {
+ if (!pInstance_)
+ {
+ MakeInstance();
+ }
+ return *pInstance_;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // SingletonHolder::MakeInstance (helper for Instance)
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ class T,
+ template <class> class CreationPolicy,
+ template <class> class LifetimePolicy,
+ template <class, class> class ThreadingModel,
+ class MutexPolicy
+ >
+ void SingletonHolder<T, CreationPolicy,
+ LifetimePolicy, ThreadingModel, MutexPolicy>::MakeInstance()
+ {
+ typename ThreadingModel<SingletonHolder,MutexPolicy>::Lock guard;
+ (void)guard;
+
+ if (!pInstance_)
+ {
+ if (destroyed_)
+ {
+ destroyed_ = false;
+ LifetimePolicy<T>::OnDeadReference();
+ }
+ pInstance_ = CreationPolicy<T>::Create();
+ LifetimePolicy<T>::ScheduleDestruction(pInstance_,
+ &DestroySingleton);
+ }
+ }
+
+ template
+ <
+ class T,
+ template <class> class CreationPolicy,
+ template <class> class L,
+ template <class, class> class M,
+ class X
+ >
+ void LOKI_C_CALLING_CONVENTION_QUALIFIER
+ SingletonHolder<T, CreationPolicy, L, M, X>::DestroySingleton()
+ {
+ assert(!destroyed_);
+ CreationPolicy<T>::Destroy(pInstance_);
+ pInstance_ = 0;
+ destroyed_ = true;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class Singleton
+ ///
+ /// \ingroup SingletonGroup
+ ///
+ /// Convenience template to implement a getter function for a singleton object.
+ /// Often needed in a shared library which hosts singletons.
+ ///
+ /// \par Usage
+ ///
+ /// see test/SingletonDll
+ ///
+ ////////////////////////////////////////////////////////////////////////////////
+
+#ifndef LOKI_SINGLETON_EXPORT
+#define LOKI_SINGLETON_EXPORT
+#endif
+
+ template<class T>
+ class LOKI_SINGLETON_EXPORT Singleton
+ {
+ public:
+ static T& Instance();
+ };
+
+} // namespace Loki
+
+
+/// \def LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER)
+/// Convenience macro for the definition of the static Instance member function
+/// Put this macro called with a SingletonHolder typedef into your cpp file.
+
+#define LOKI_SINGLETON_INSTANCE_DEFINITION(SHOLDER) \
+namespace Loki \
+{ \
+ template<> \
+ SHOLDER::ObjectType& Singleton<SHOLDER::ObjectType>::Instance() \
+ { \
+ return SHOLDER::Instance(); \
+ } \
+}
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/SmallObj.cpp b/shared/loki/SmallObj.cpp
new file mode 100644
index 00000000..a2911bb1
--- /dev/null
+++ b/shared/loki/SmallObj.cpp
@@ -0,0 +1,1226 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+
+// $Id: SmallObj.cpp 823 2007-05-08 10:48:40Z lfittl $
+
+
+#include <loki/SmallObj.h>
+
+#include <cassert>
+#include <climits>
+#include <vector>
+#include <bitset>
+
+//#define DO_EXTRA_LOKI_TESTS
+//#define USE_NEW_TO_ALLOCATE
+//#define LOKI_CHECK_FOR_CORRUPTION
+
+#ifdef DO_EXTRA_LOKI_TESTS
+ #include <iostream>
+#endif
+
+namespace Loki
+{
+
+ /** @struct Chunk
+ @ingroup SmallObjectGroupInternal
+ Contains info about each allocated Chunk - which is a collection of
+ contiguous blocks. Each block is the same size, as specified by the
+ FixedAllocator. The number of blocks in a Chunk depends upon page size.
+ This is a POD-style struct with value-semantics. All functions and data
+ are private so that they can not be changed by anything other than the
+ FixedAllocator which owns the Chunk.
+
+ @par Minimal Interface
+ For the sake of runtime efficiency, no constructor, destructor, or
+ copy-assignment operator is defined. The inline functions made by the
+ compiler should be sufficient, and perhaps faster than hand-crafted
+ functions. The lack of these functions allows vector to create and copy
+ Chunks as needed without overhead. The Init and Release functions do
+ what the default constructor and destructor would do. A Chunk is not in
+ a usable state after it is constructed and before calling Init. Nor is
+ a Chunk usable after Release is called, but before the destructor.
+
+ @par Efficiency
+ Down near the lowest level of the allocator, runtime efficiencies trump
+ almost all other considerations. Each function does the minimum required
+ of it. All functions should execute in constant time to prevent higher-
+ level code from unwittingly using a version of Shlemiel the Painter's
+ Algorithm.
+
+ @par Stealth Indexes
+ The first char of each empty block contains the index of the next empty
+ block. These stealth indexes form a singly-linked list within the blocks.
+ A Chunk is corrupt if this singly-linked list has a loop or is shorter
+ than blocksAvailable_. Much of the allocator's time and space efficiency
+ comes from how these stealth indexes are implemented.
+ */
+ class Chunk
+ {
+ private:
+ friend class FixedAllocator;
+
+ /** Initializes a just-constructed Chunk.
+ @param blockSize Number of bytes per block.
+ @param blocks Number of blocks per Chunk.
+ @return True for success, false for failure.
+ */
+ bool Init( std::size_t blockSize, unsigned char blocks );
+
+ /** Allocate a block within the Chunk. Complexity is always O(1), and
+ this will never throw. Does not actually "allocate" by calling
+ malloc, new, or any other function, but merely adjusts some internal
+ indexes to indicate an already allocated block is no longer available.
+ @return Pointer to block within Chunk.
+ */
+ void * Allocate( std::size_t blockSize );
+
+ /** Deallocate a block within the Chunk. Complexity is always O(1), and
+ this will never throw. For efficiency, this assumes the address is
+ within the block and aligned along the correct byte boundary. An
+ assertion checks the alignment, and a call to HasBlock is done from
+ within VicinityFind. Does not actually "deallocate" by calling free,
+ delete, or other function, but merely adjusts some internal indexes to
+ indicate a block is now available.
+ */
+ void Deallocate( void * p, std::size_t blockSize );
+
+ /** Resets the Chunk back to pristine values. The available count is
+ set back to zero, and the first available index is set to the zeroth
+ block. The stealth indexes inside each block are set to point to the
+ next block. This assumes the Chunk's data was already using Init.
+ */
+ void Reset( std::size_t blockSize, unsigned char blocks );
+
+ /// Releases the allocated block of memory.
+ void Release();
+
+ /** Determines if the Chunk has been corrupted.
+ @param numBlocks Total # of blocks in the Chunk.
+ @param blockSize # of bytes in each block.
+ @param checkIndexes True if caller wants to check indexes of available
+ blocks for corruption. If false, then caller wants to skip some
+ tests tests just to run faster. (Debug version does more checks, but
+ release version runs faster.)
+ @return True if Chunk is corrupt.
+ */
+ bool IsCorrupt( unsigned char numBlocks, std::size_t blockSize,
+ bool checkIndexes ) const;
+
+ /** Determines if block is available.
+ @param p Address of block managed by Chunk.
+ @param numBlocks Total # of blocks in the Chunk.
+ @param blockSize # of bytes in each block.
+ @return True if block is available, else false if allocated.
+ */
+ bool IsBlockAvailable( void * p, unsigned char numBlocks,
+ std::size_t blockSize ) const;
+
+ /// Returns true if block at address P is inside this Chunk.
+ inline bool HasBlock( void * p, std::size_t chunkLength ) const
+ {
+ unsigned char * pc = static_cast< unsigned char * >( p );
+ return ( pData_ <= pc ) && ( pc < pData_ + chunkLength );
+ }
+
+ inline bool HasAvailable( unsigned char numBlocks ) const
+ { return ( blocksAvailable_ == numBlocks ); }
+
+ inline bool IsFilled( void ) const
+ { return ( 0 == blocksAvailable_ ); }
+
+ /// Pointer to array of allocated blocks.
+ unsigned char * pData_;
+ /// Index of first empty block.
+ unsigned char firstAvailableBlock_;
+ /// Count of empty blocks.
+ unsigned char blocksAvailable_;
+ };
+
+ /** @class FixedAllocator
+ @ingroup SmallObjectGroupInternal
+ Offers services for allocating fixed-sized objects. It has a container
+ of "containers" of fixed-size blocks. The outer container has all the
+ Chunks. The inner container is a Chunk which owns some blocks.
+
+ @par Class Level Invariants
+ - There is always either zero or one Chunk which is empty.
+ - If this has no empty Chunk, then emptyChunk_ is NULL.
+ - If this has an empty Chunk, then emptyChunk_ points to it.
+ - If the Chunk container is empty, then deallocChunk_ and allocChunk_
+ are NULL.
+ - If the Chunk container is not-empty, then deallocChunk_ and allocChunk_
+ are either NULL or point to Chunks within the container.
+ - allocChunk_ will often point to the last Chunk in the container since
+ it was likely allocated most recently, and therefore likely to have an
+ available block.
+ */
+ class FixedAllocator
+ {
+ private:
+
+ /** Deallocates the block at address p, and then handles the internal
+ bookkeeping needed to maintain class invariants. This assumes that
+ deallocChunk_ points to the correct chunk.
+ */
+ void DoDeallocate( void * p );
+
+ /** Creates an empty Chunk and adds it to the end of the ChunkList.
+ All calls to the lower-level memory allocation functions occur inside
+ this function, and so the only try-catch block is inside here.
+ @return true for success, false for failure.
+ */
+ bool MakeNewChunk( void );
+
+ /** Finds the Chunk which owns the block at address p. It starts at
+ deallocChunk_ and searches in both forwards and backwards directions
+ from there until it finds the Chunk which owns p. This algorithm
+ should find the Chunk quickly if it is deallocChunk_ or is close to it
+ in the Chunks container. This goes both forwards and backwards since
+ that works well for both same-order and opposite-order deallocations.
+ (Same-order = objects are deallocated in the same order in which they
+ were allocated. Opposite order = objects are deallocated in a last to
+ first order. Complexity is O(C) where C is count of all Chunks. This
+ never throws.
+ @return Pointer to Chunk that owns p, or NULL if no owner found.
+ */
+ Chunk * VicinityFind( void * p ) const;
+
+ /// Not implemented.
+ FixedAllocator(const FixedAllocator&);
+ /// Not implemented.
+ FixedAllocator& operator=(const FixedAllocator&);
+
+ /// Type of container used to hold Chunks.
+ typedef std::vector< Chunk > Chunks;
+ /// Iterator through container of Chunks.
+ typedef Chunks::iterator ChunkIter;
+ /// Iterator through const container of Chunks.
+ typedef Chunks::const_iterator ChunkCIter;
+
+ /// Fewest # of objects managed by a Chunk.
+ static unsigned char MinObjectsPerChunk_;
+
+ /// Most # of objects managed by a Chunk - never exceeds UCHAR_MAX.
+ static unsigned char MaxObjectsPerChunk_;
+
+ /// Number of bytes in a single block within a Chunk.
+ std::size_t blockSize_;
+ /// Number of blocks managed by each Chunk.
+ unsigned char numBlocks_;
+
+ /// Container of Chunks.
+ Chunks chunks_;
+ /// Pointer to Chunk used for last or next allocation.
+ Chunk * allocChunk_;
+ /// Pointer to Chunk used for last or next deallocation.
+ Chunk * deallocChunk_;
+ /// Pointer to the only empty Chunk if there is one, else NULL.
+ Chunk * emptyChunk_;
+
+ public:
+ /// Create a FixedAllocator which manages blocks of 'blockSize' size.
+ FixedAllocator();
+
+ /// Destroy the FixedAllocator and release all its Chunks.
+ ~FixedAllocator();
+
+ /// Initializes a FixedAllocator by calculating # of blocks per Chunk.
+ void Initialize( std::size_t blockSize, std::size_t pageSize );
+
+ /** Returns pointer to allocated memory block of fixed size - or NULL
+ if it failed to allocate.
+ */
+ void * Allocate( void );
+
+ /** Deallocate a memory block previously allocated with Allocate. If
+ the block is not owned by this FixedAllocator, it returns false so
+ that SmallObjAllocator can call the default deallocator. If the
+ block was found, this returns true.
+ */
+ bool Deallocate( void * p, Chunk * hint );
+
+ /// Returns block size with which the FixedAllocator was initialized.
+ inline std::size_t BlockSize() const { return blockSize_; }
+
+ /** Releases the memory used by the empty Chunk. This will take
+ constant time under any situation.
+ @return True if empty chunk found and released, false if none empty.
+ */
+ bool TrimEmptyChunk( void );
+
+ /** Releases unused spots from ChunkList. This takes constant time
+ with respect to # of Chunks, but actual time depends on underlying
+ memory allocator.
+ @return False if no unused spots, true if some found and released.
+ */
+ bool TrimChunkList( void );
+
+ /** Returns count of empty Chunks held by this allocator. Complexity
+ is O(C) where C is the total number of Chunks - empty or used.
+ */
+ std::size_t CountEmptyChunks( void ) const;
+
+ /** Determines if FixedAllocator is corrupt. Checks data members to
+ see if any have erroneous values, or violate class invariants. It
+ also checks if any Chunk is corrupt. Complexity is O(C) where C is
+ the number of Chunks. If any data is corrupt, this will return true
+ in release mode, or assert in debug mode.
+ */
+ bool IsCorrupt( void ) const;
+
+ /** Returns true if the block at address p is within a Chunk owned by
+ this FixedAllocator. Complexity is O(C) where C is the total number
+ of Chunks - empty or used.
+ */
+ const Chunk * HasBlock( void * p ) const;
+ inline Chunk * HasBlock( void * p )
+ {
+ return const_cast< Chunk * >(
+ const_cast< const FixedAllocator * >( this )->HasBlock( p ) );
+ }
+
+ };
+
+ unsigned char FixedAllocator::MinObjectsPerChunk_ = 8;
+ unsigned char FixedAllocator::MaxObjectsPerChunk_ = UCHAR_MAX;
+
+// Chunk::Init ----------------------------------------------------------------
+
+bool Chunk::Init( std::size_t blockSize, unsigned char blocks )
+{
+ assert(blockSize > 0);
+ assert(blocks > 0);
+ // Overflow check
+ const std::size_t allocSize = blockSize * blocks;
+ assert( allocSize / blockSize == blocks);
+
+#ifdef USE_NEW_TO_ALLOCATE
+ // If this new operator fails, it will throw, and the exception will get
+ // caught one layer up.
+ pData_ = static_cast< unsigned char * >( ::operator new ( allocSize ) );
+#else
+ // malloc can't throw, so its only way to indicate an error is to return
+ // a NULL pointer, so we have to check for that.
+ pData_ = static_cast< unsigned char * >( ::std::malloc( allocSize ) );
+ if ( NULL == pData_ ) return false;
+#endif
+
+ Reset( blockSize, blocks );
+ return true;
+}
+
+// Chunk::Reset ---------------------------------------------------------------
+
+void Chunk::Reset(std::size_t blockSize, unsigned char blocks)
+{
+ assert(blockSize > 0);
+ assert(blocks > 0);
+ // Overflow check
+ assert((blockSize * blocks) / blockSize == blocks);
+
+ firstAvailableBlock_ = 0;
+ blocksAvailable_ = blocks;
+
+ unsigned char i = 0;
+ for ( unsigned char * p = pData_; i != blocks; p += blockSize )
+ {
+ *p = ++i;
+ }
+}
+
+// Chunk::Release -------------------------------------------------------------
+
+void Chunk::Release()
+{
+ assert( NULL != pData_ );
+#ifdef USE_NEW_TO_ALLOCATE
+ ::operator delete ( pData_ );
+#else
+ ::std::free( static_cast< void * >( pData_ ) );
+#endif
+}
+
+// Chunk::Allocate ------------------------------------------------------------
+
+void* Chunk::Allocate(std::size_t blockSize)
+{
+ if ( IsFilled() ) return NULL;
+
+ assert((firstAvailableBlock_ * blockSize) / blockSize ==
+ firstAvailableBlock_);
+ unsigned char * pResult = pData_ + (firstAvailableBlock_ * blockSize);
+ firstAvailableBlock_ = *pResult;
+ --blocksAvailable_;
+
+ return pResult;
+}
+
+// Chunk::Deallocate ----------------------------------------------------------
+
+void Chunk::Deallocate(void* p, std::size_t blockSize)
+{
+ assert(p >= pData_);
+
+ unsigned char* toRelease = static_cast<unsigned char*>(p);
+ // Alignment check
+ assert((toRelease - pData_) % blockSize == 0);
+ unsigned char index = static_cast< unsigned char >(
+ ( toRelease - pData_ ) / blockSize);
+
+#if defined(DEBUG) || defined(_DEBUG)
+ // Check if block was already deleted. Attempting to delete the same
+ // block more than once causes Chunk's linked-list of stealth indexes to
+ // become corrupt. And causes count of blocksAvailable_ to be wrong.
+ if ( 0 < blocksAvailable_ )
+ assert( firstAvailableBlock_ != index );
+#endif
+
+ *toRelease = firstAvailableBlock_;
+ firstAvailableBlock_ = index;
+ // Truncation check
+ assert(firstAvailableBlock_ == (toRelease - pData_) / blockSize);
+
+ ++blocksAvailable_;
+}
+
+// Chunk::IsCorrupt -----------------------------------------------------------
+
+bool Chunk::IsCorrupt( unsigned char numBlocks, std::size_t blockSize,
+ bool checkIndexes ) const
+{
+
+ if ( numBlocks < blocksAvailable_ )
+ {
+ // Contents at this Chunk corrupted. This might mean something has
+ // overwritten memory owned by the Chunks container.
+ assert( false );
+ return true;
+ }
+ if ( IsFilled() )
+ // Useless to do further corruption checks if all blocks allocated.
+ return false;
+ unsigned char index = firstAvailableBlock_;
+ if ( numBlocks <= index )
+ {
+ // Contents at this Chunk corrupted. This might mean something has
+ // overwritten memory owned by the Chunks container.
+ assert( false );
+ return true;
+ }
+ if ( !checkIndexes )
+ // Caller chose to skip more complex corruption tests.
+ return false;
+
+ /* If the bit at index was set in foundBlocks, then the stealth index was
+ found on the linked-list.
+ */
+ std::bitset< UCHAR_MAX > foundBlocks;
+ unsigned char * nextBlock = NULL;
+
+ /* The loop goes along singly linked-list of stealth indexes and makes sure
+ that each index is within bounds (0 <= index < numBlocks) and that the
+ index was not already found while traversing the linked-list. The linked-
+ list should have exactly blocksAvailable_ nodes, so the for loop will not
+ check more than blocksAvailable_. This loop can't check inside allocated
+ blocks for corruption since such blocks are not within the linked-list.
+ Contents of allocated blocks are not changed by Chunk.
+
+ Here are the types of corrupted link-lists which can be verified. The
+ corrupt index is shown with asterisks in each example.
+
+ Type 1: Index is too big.
+ numBlocks == 64
+ blocksAvailable_ == 7
+ firstAvailableBlock_ -> 17 -> 29 -> *101*
+ There should be no indexes which are equal to or larger than the total
+ number of blocks. Such an index would refer to a block beyond the
+ Chunk's allocated domain.
+
+ Type 2: Index is repeated.
+ numBlocks == 64
+ blocksAvailable_ == 5
+ firstAvailableBlock_ -> 17 -> 29 -> 53 -> *17* -> 29 -> 53 ...
+ No index should be repeated within the linked-list since that would
+ indicate the presence of a loop in the linked-list.
+ */
+ for ( unsigned char cc = 0; ; )
+ {
+ nextBlock = pData_ + ( index * blockSize );
+ foundBlocks.set( index, true );
+ ++cc;
+ if ( cc >= blocksAvailable_ )
+ // Successfully counted off number of nodes in linked-list.
+ break;
+ index = *nextBlock;
+ if ( numBlocks <= index )
+ {
+ /* This catches Type 1 corruptions as shown in above comments.
+ This implies that a block was corrupted due to a stray pointer
+ or an operation on a nearby block overran the size of the block.
+ */
+ assert( false );
+ return true;
+ }
+ if ( foundBlocks.test( index ) )
+ {
+ /* This catches Type 2 corruptions as shown in above comments.
+ This implies that a block was corrupted due to a stray pointer
+ or an operation on a nearby block overran the size of the block.
+ Or perhaps the program tried to delete a block more than once.
+ */
+ assert( false );
+ return true;
+ }
+ }
+ if ( foundBlocks.count() != blocksAvailable_ )
+ {
+ /* This implies that the singly-linked-list of stealth indexes was
+ corrupted. Ideally, this should have been detected within the loop.
+ */
+ assert( false );
+ return true;
+ }
+
+ return false;
+}
+
+// Chunk::IsBlockAvailable ----------------------------------------------------
+
+bool Chunk::IsBlockAvailable( void * p, unsigned char numBlocks,
+ std::size_t blockSize ) const
+{
+ (void) numBlocks;
+
+ if ( IsFilled() )
+ return false;
+
+ unsigned char * place = static_cast< unsigned char * >( p );
+ // Alignment check
+ assert( ( place - pData_ ) % blockSize == 0 );
+ unsigned char blockIndex = static_cast< unsigned char >(
+ ( place - pData_ ) / blockSize );
+
+ unsigned char index = firstAvailableBlock_;
+ assert( numBlocks > index );
+ if ( index == blockIndex )
+ return true;
+
+ /* If the bit at index was set in foundBlocks, then the stealth index was
+ found on the linked-list.
+ */
+ std::bitset< UCHAR_MAX > foundBlocks;
+ unsigned char * nextBlock = NULL;
+ for ( unsigned char cc = 0; ; )
+ {
+ nextBlock = pData_ + ( index * blockSize );
+ foundBlocks.set( index, true );
+ ++cc;
+ if ( cc >= blocksAvailable_ )
+ // Successfully counted off number of nodes in linked-list.
+ break;
+ index = *nextBlock;
+ if ( index == blockIndex )
+ return true;
+ assert( numBlocks > index );
+ assert( !foundBlocks.test( index ) );
+ }
+
+ return false;
+}
+
+// FixedAllocator::FixedAllocator ---------------------------------------------
+
+FixedAllocator::FixedAllocator()
+ : blockSize_( 0 )
+ , numBlocks_( 0 )
+ , chunks_( 0 )
+ , allocChunk_( NULL )
+ , deallocChunk_( NULL )
+ , emptyChunk_( NULL )
+{
+}
+
+// FixedAllocator::~FixedAllocator --------------------------------------------
+
+FixedAllocator::~FixedAllocator()
+{
+#ifdef DO_EXTRA_LOKI_TESTS
+ TrimEmptyChunk();
+ assert( chunks_.empty() && "Memory leak detected!" );
+#endif
+ for ( ChunkIter i( chunks_.begin() ); i != chunks_.end(); ++i )
+ i->Release();
+}
+
+// FixedAllocator::Initialize -------------------------------------------------
+
+void FixedAllocator::Initialize( std::size_t blockSize, std::size_t pageSize )
+{
+ assert( blockSize > 0 );
+ assert( pageSize >= blockSize );
+ blockSize_ = blockSize;
+
+ std::size_t numBlocks = pageSize / blockSize;
+ if ( numBlocks > MaxObjectsPerChunk_ ) numBlocks = MaxObjectsPerChunk_;
+ else if ( numBlocks < MinObjectsPerChunk_ ) numBlocks = MinObjectsPerChunk_;
+
+ numBlocks_ = static_cast<unsigned char>(numBlocks);
+ assert(numBlocks_ == numBlocks);
+}
+
+// FixedAllocator::CountEmptyChunks -------------------------------------------
+
+std::size_t FixedAllocator::CountEmptyChunks( void ) const
+{
+#ifdef DO_EXTRA_LOKI_TESTS
+ // This code is only used for specialized tests of the allocator.
+ // It is #ifdef-ed so that its O(C) complexity does not overwhelm the
+ // functions which call it.
+ std::size_t count = 0;
+ for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it )
+ {
+ const Chunk & chunk = *it;
+ if ( chunk.HasAvailable( numBlocks_ ) )
+ ++count;
+ }
+ return count;
+#else
+ return ( NULL == emptyChunk_ ) ? 0 : 1;
+#endif
+}
+
+// FixedAllocator::IsCorrupt --------------------------------------------------
+
+bool FixedAllocator::IsCorrupt( void ) const
+{
+ const bool isEmpty = chunks_.empty();
+ ChunkCIter start( chunks_.begin() );
+ ChunkCIter last( chunks_.end() );
+ const size_t emptyChunkCount = CountEmptyChunks();
+
+ if ( isEmpty )
+ {
+ if ( start != last )
+ {
+ assert( false );
+ return true;
+ }
+ if ( 0 < emptyChunkCount )
+ {
+ assert( false );
+ return true;
+ }
+ if ( NULL != deallocChunk_ )
+ {
+ assert( false );
+ return true;
+ }
+ if ( NULL != allocChunk_ )
+ {
+ assert( false );
+ return true;
+ }
+ if ( NULL != emptyChunk_ )
+ {
+ assert( false );
+ return true;
+ }
+ }
+
+ else
+ {
+ const Chunk * front = &chunks_.front();
+ const Chunk * back = &chunks_.back();
+ if ( start >= last )
+ {
+ assert( false );
+ return true;
+ }
+ if ( back < deallocChunk_ )
+ {
+ assert( false );
+ return true;
+ }
+ if ( back < allocChunk_ )
+ {
+ assert( false );
+ return true;
+ }
+ if ( front > deallocChunk_ )
+ {
+ assert( false );
+ return true;
+ }
+ if ( front > allocChunk_ )
+ {
+ assert( false );
+ return true;
+ }
+
+ switch ( emptyChunkCount )
+ {
+ case 0:
+ if ( emptyChunk_ != NULL )
+ {
+ assert( false );
+ return true;
+ }
+ break;
+ case 1:
+ if ( emptyChunk_ == NULL )
+ {
+ assert( false );
+ return true;
+ }
+ if ( back < emptyChunk_ )
+ {
+ assert( false );
+ return true;
+ }
+ if ( front > emptyChunk_ )
+ {
+ assert( false );
+ return true;
+ }
+ if ( !emptyChunk_->HasAvailable( numBlocks_ ) )
+ {
+ // This may imply somebody tried to delete a block twice.
+ assert( false );
+ return true;
+ }
+ break;
+ default:
+ assert( false );
+ return true;
+ }
+ for ( ChunkCIter it( start ); it != last; ++it )
+ {
+ const Chunk & chunk = *it;
+ if ( chunk.IsCorrupt( numBlocks_, blockSize_, true ) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// FixedAllocator::HasBlock ---------------------------------------------------
+
+const Chunk * FixedAllocator::HasBlock( void * p ) const
+{
+ const std::size_t chunkLength = numBlocks_ * blockSize_;
+ for ( ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it )
+ {
+ const Chunk & chunk = *it;
+ if ( chunk.HasBlock( p, chunkLength ) )
+ return &chunk;
+ }
+ return NULL;
+}
+
+// FixedAllocator::TrimEmptyChunk ---------------------------------------------
+
+bool FixedAllocator::TrimEmptyChunk( void )
+{
+ // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
+ assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
+ if ( NULL == emptyChunk_ ) return false;
+
+ // If emptyChunk_ points to valid Chunk, then chunk list is not empty.
+ assert( !chunks_.empty() );
+ // And there should be exactly 1 empty Chunk.
+ assert( 1 == CountEmptyChunks() );
+
+ Chunk * lastChunk = &chunks_.back();
+ if ( lastChunk != emptyChunk_ )
+ std::swap( *emptyChunk_, *lastChunk );
+ assert( lastChunk->HasAvailable( numBlocks_ ) );
+ lastChunk->Release();
+ chunks_.pop_back();
+
+ if ( chunks_.empty() )
+ {
+ allocChunk_ = NULL;
+ deallocChunk_ = NULL;
+ }
+ else
+ {
+ if ( deallocChunk_ == emptyChunk_ )
+ {
+ deallocChunk_ = &chunks_.front();
+ assert( deallocChunk_->blocksAvailable_ < numBlocks_ );
+ }
+ if ( allocChunk_ == emptyChunk_ )
+ {
+ allocChunk_ = &chunks_.back();
+ assert( allocChunk_->blocksAvailable_ < numBlocks_ );
+ }
+ }
+
+ emptyChunk_ = NULL;
+ assert( 0 == CountEmptyChunks() );
+
+ return true;
+}
+
+// FixedAllocator::TrimChunkList ----------------------------------------------
+
+bool FixedAllocator::TrimChunkList( void )
+{
+ if ( chunks_.empty() )
+ {
+ assert( NULL == allocChunk_ );
+ assert( NULL == deallocChunk_ );
+ }
+
+ if ( chunks_.size() == chunks_.capacity() )
+ return false;
+ // Use the "make-a-temp-and-swap" trick to remove excess capacity.
+ Chunks( chunks_ ).swap( chunks_ );
+
+ return true;
+}
+
+// FixedAllocator::MakeNewChunk -----------------------------------------------
+
+bool FixedAllocator::MakeNewChunk( void )
+{
+ bool allocated = false;
+ try
+ {
+ std::size_t size = chunks_.size();
+ // Calling chunks_.reserve *before* creating and initializing the new
+ // Chunk means that nothing is leaked by this function in case an
+ // exception is thrown from reserve.
+ if ( chunks_.capacity() == size )
+ {
+ if ( 0 == size ) size = 4;
+ chunks_.reserve( size * 2 );
+ }
+ Chunk newChunk;
+ allocated = newChunk.Init( blockSize_, numBlocks_ );
+ if ( allocated )
+ chunks_.push_back( newChunk );
+ }
+ catch ( ... )
+ {
+ allocated = false;
+ }
+ if ( !allocated ) return false;
+
+ allocChunk_ = &chunks_.back();
+ deallocChunk_ = &chunks_.front();
+ return true;
+}
+
+// FixedAllocator::Allocate ---------------------------------------------------
+
+void * FixedAllocator::Allocate( void )
+{
+ // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
+ assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
+ assert( CountEmptyChunks() < 2 );
+
+ if ( ( NULL == allocChunk_ ) || allocChunk_->IsFilled() )
+ {
+ if ( NULL != emptyChunk_ )
+ {
+ allocChunk_ = emptyChunk_;
+ emptyChunk_ = NULL;
+ }
+ else
+ {
+ for ( ChunkIter i( chunks_.begin() ); ; ++i )
+ {
+ if ( chunks_.end() == i )
+ {
+ if ( !MakeNewChunk() )
+ return NULL;
+ break;
+ }
+ if ( !i->IsFilled() )
+ {
+ allocChunk_ = &*i;
+ break;
+ }
+ }
+ }
+ }
+ else if ( allocChunk_ == emptyChunk_)
+ // detach emptyChunk_ from allocChunk_, because after
+ // calling allocChunk_->Allocate(blockSize_); the chunk
+ // is no longer empty.
+ emptyChunk_ = NULL;
+
+ assert( allocChunk_ != NULL );
+ assert( !allocChunk_->IsFilled() );
+ void * place = allocChunk_->Allocate( blockSize_ );
+
+ // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
+ assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
+ assert( CountEmptyChunks() < 2 );
+#ifdef LOKI_CHECK_FOR_CORRUPTION
+ if ( allocChunk_->IsCorrupt( numBlocks_, blockSize_, true ) )
+ {
+ assert( false );
+ return NULL;
+ }
+#endif
+
+ return place;
+}
+
+// FixedAllocator::Deallocate -------------------------------------------------
+
+bool FixedAllocator::Deallocate( void * p, Chunk * hint )
+{
+ assert(!chunks_.empty());
+ assert(&chunks_.front() <= deallocChunk_);
+ assert(&chunks_.back() >= deallocChunk_);
+ assert( &chunks_.front() <= allocChunk_ );
+ assert( &chunks_.back() >= allocChunk_ );
+ assert( CountEmptyChunks() < 2 );
+
+ Chunk * foundChunk = ( NULL == hint ) ? VicinityFind( p ) : hint;
+ if ( NULL == foundChunk )
+ return false;
+
+ assert( foundChunk->HasBlock( p, numBlocks_ * blockSize_ ) );
+#ifdef LOKI_CHECK_FOR_CORRUPTION
+ if ( foundChunk->IsCorrupt( numBlocks_, blockSize_, true ) )
+ {
+ assert( false );
+ return false;
+ }
+ if ( foundChunk->IsBlockAvailable( p, numBlocks_, blockSize_ ) )
+ {
+ assert( false );
+ return false;
+ }
+#endif
+ deallocChunk_ = foundChunk;
+ DoDeallocate(p);
+ assert( CountEmptyChunks() < 2 );
+
+ return true;
+}
+
+// FixedAllocator::VicinityFind -----------------------------------------------
+
+Chunk * FixedAllocator::VicinityFind( void * p ) const
+{
+ if ( chunks_.empty() ) return NULL;
+ assert(deallocChunk_);
+
+ const std::size_t chunkLength = numBlocks_ * blockSize_;
+ Chunk * lo = deallocChunk_;
+ Chunk * hi = deallocChunk_ + 1;
+ const Chunk * loBound = &chunks_.front();
+ const Chunk * hiBound = &chunks_.back() + 1;
+
+ // Special case: deallocChunk_ is the last in the array
+ if (hi == hiBound) hi = NULL;
+
+ for (;;)
+ {
+ if (lo)
+ {
+ if ( lo->HasBlock( p, chunkLength ) ) return lo;
+ if ( lo == loBound )
+ {
+ lo = NULL;
+ if ( NULL == hi ) break;
+ }
+ else --lo;
+ }
+
+ if (hi)
+ {
+ if ( hi->HasBlock( p, chunkLength ) ) return hi;
+ if ( ++hi == hiBound )
+ {
+ hi = NULL;
+ if ( NULL == lo ) break;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// FixedAllocator::DoDeallocate -----------------------------------------------
+
+void FixedAllocator::DoDeallocate(void* p)
+{
+ // Show that deallocChunk_ really owns the block at address p.
+ assert( deallocChunk_->HasBlock( p, numBlocks_ * blockSize_ ) );
+ // Either of the next two assertions may fail if somebody tries to
+ // delete the same block twice.
+ assert( emptyChunk_ != deallocChunk_ );
+ assert( !deallocChunk_->HasAvailable( numBlocks_ ) );
+ // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
+ assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
+
+ // call into the chunk, will adjust the inner list but won't release memory
+ deallocChunk_->Deallocate(p, blockSize_);
+
+ if ( deallocChunk_->HasAvailable( numBlocks_ ) )
+ {
+ assert( emptyChunk_ != deallocChunk_ );
+ // deallocChunk_ is empty, but a Chunk is only released if there are 2
+ // empty chunks. Since emptyChunk_ may only point to a previously
+ // cleared Chunk, if it points to something else besides deallocChunk_,
+ // then FixedAllocator currently has 2 empty Chunks.
+ if ( NULL != emptyChunk_ )
+ {
+ // If last Chunk is empty, just change what deallocChunk_
+ // points to, and release the last. Otherwise, swap an empty
+ // Chunk with the last, and then release it.
+ Chunk * lastChunk = &chunks_.back();
+ if ( lastChunk == deallocChunk_ )
+ deallocChunk_ = emptyChunk_;
+ else if ( lastChunk != emptyChunk_ )
+ std::swap( *emptyChunk_, *lastChunk );
+ assert( lastChunk->HasAvailable( numBlocks_ ) );
+ lastChunk->Release();
+ chunks_.pop_back();
+ if ( ( allocChunk_ == lastChunk ) || allocChunk_->IsFilled() )
+ allocChunk_ = deallocChunk_;
+ }
+ emptyChunk_ = deallocChunk_;
+ }
+
+ // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
+ assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
+}
+
+// GetOffset ------------------------------------------------------------------
+/// @ingroup SmallObjectGroupInternal
+/// Calculates index into array where a FixedAllocator of numBytes is located.
+inline std::size_t GetOffset( std::size_t numBytes, std::size_t alignment )
+{
+ const std::size_t alignExtra = alignment-1;
+ return ( numBytes + alignExtra ) / alignment;
+}
+
+// DefaultAllocator -----------------------------------------------------------
+/** @ingroup SmallObjectGroupInternal
+ Calls the default allocator when SmallObjAllocator decides not to handle a
+ request. SmallObjAllocator calls this if the number of bytes is bigger than
+ the size which can be handled by any FixedAllocator.
+ @param numBytes number of bytes
+ @param doThrow True if this function should throw an exception, or false if it
+ should indicate failure by returning a NULL pointer.
+*/
+void * DefaultAllocator( std::size_t numBytes, bool doThrow )
+{
+#ifdef USE_NEW_TO_ALLOCATE
+ return doThrow ? ::operator new( numBytes ) :
+ ::operator new( numBytes, std::nothrow_t() );
+#else
+ void * p = ::std::malloc( numBytes );
+ if ( doThrow && ( NULL == p ) )
+ throw std::bad_alloc();
+ return p;
+#endif
+}
+
+// DefaultDeallocator ---------------------------------------------------------
+/** @ingroup SmallObjectGroupInternal
+ Calls default deallocator when SmallObjAllocator decides not to handle a
+ request. The default deallocator could be the global delete operator or the
+ free function. The free function is the preferred default deallocator since
+ it matches malloc which is the preferred default allocator. SmallObjAllocator
+ will call this if an address was not found among any of its own blocks.
+ */
+void DefaultDeallocator( void * p )
+{
+#ifdef USE_NEW_TO_ALLOCATE
+ ::operator delete( p );
+#else
+ ::std::free( p );
+#endif
+}
+
+// SmallObjAllocator::SmallObjAllocator ---------------------------------------
+
+SmallObjAllocator::SmallObjAllocator( std::size_t pageSize,
+ std::size_t maxObjectSize, std::size_t objectAlignSize ) :
+ pool_( NULL ),
+ maxSmallObjectSize_( maxObjectSize ),
+ objectAlignSize_( objectAlignSize )
+{
+#ifdef DO_EXTRA_LOKI_TESTS
+ std::cout << "SmallObjAllocator " << this << std::endl;
+#endif
+ assert( 0 != objectAlignSize );
+ const std::size_t allocCount = GetOffset( maxObjectSize, objectAlignSize );
+ pool_ = new FixedAllocator[ allocCount ];
+ for ( std::size_t i = 0; i < allocCount; ++i )
+ pool_[ i ].Initialize( ( i+1 ) * objectAlignSize, pageSize );
+}
+
+// SmallObjAllocator::~SmallObjAllocator --------------------------------------
+
+SmallObjAllocator::~SmallObjAllocator( void )
+{
+#ifdef DO_EXTRA_LOKI_TESTS
+ std::cout << "~SmallObjAllocator " << this << std::endl;
+#endif
+ delete [] pool_;
+}
+
+// SmallObjAllocator::TrimExcessMemory ----------------------------------------
+
+bool SmallObjAllocator::TrimExcessMemory( void )
+{
+ bool found = false;
+ const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
+ std::size_t i = 0;
+ for ( ; i < allocCount; ++i )
+ {
+ if ( pool_[ i ].TrimEmptyChunk() )
+ found = true;
+ }
+ for ( i = 0; i < allocCount; ++i )
+ {
+ if ( pool_[ i ].TrimChunkList() )
+ found = true;
+ }
+
+ return found;
+}
+
+// SmallObjAllocator::Allocate ------------------------------------------------
+
+void * SmallObjAllocator::Allocate( std::size_t numBytes, bool doThrow )
+{
+ if ( numBytes > GetMaxObjectSize() )
+ return DefaultAllocator( numBytes, doThrow );
+
+ assert( NULL != pool_ );
+ if ( 0 == numBytes ) numBytes = 1;
+ const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
+ const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
+ (void) allocCount;
+ assert( index < allocCount );
+
+ FixedAllocator & allocator = pool_[ index ];
+ assert( allocator.BlockSize() >= numBytes );
+ assert( allocator.BlockSize() < numBytes + GetAlignment() );
+ void * place = allocator.Allocate();
+
+ if ( ( NULL == place ) && TrimExcessMemory() )
+ place = allocator.Allocate();
+
+ if ( ( NULL == place ) && doThrow )
+ {
+#ifdef _MSC_VER
+ throw std::bad_alloc( "could not allocate small object" );
+#else
+ // GCC did not like a literal string passed to std::bad_alloc.
+ // so just throw the default-constructed exception.
+ throw std::bad_alloc();
+#endif
+ }
+ return place;
+}
+
+// SmallObjAllocator::Deallocate ----------------------------------------------
+
+void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes )
+{
+ if ( NULL == p ) return;
+ if ( numBytes > GetMaxObjectSize() )
+ {
+ DefaultDeallocator( p );
+ return;
+ }
+ assert( NULL != pool_ );
+ if ( 0 == numBytes ) numBytes = 1;
+ const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
+ const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
+ (void) allocCount;
+ assert( index < allocCount );
+ FixedAllocator & allocator = pool_[ index ];
+ assert( allocator.BlockSize() >= numBytes );
+ assert( allocator.BlockSize() < numBytes + GetAlignment() );
+ const bool found = allocator.Deallocate( p, NULL );
+ (void) found;
+ assert( found );
+}
+
+// SmallObjAllocator::Deallocate ----------------------------------------------
+
+void SmallObjAllocator::Deallocate( void * p )
+{
+ if ( NULL == p ) return;
+ assert( NULL != pool_ );
+ FixedAllocator * pAllocator = NULL;
+ const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
+ Chunk * chunk = NULL;
+
+ for ( std::size_t ii = 0; ii < allocCount; ++ii )
+ {
+ chunk = pool_[ ii ].HasBlock( p );
+ if ( NULL != chunk )
+ {
+ pAllocator = &pool_[ ii ];
+ break;
+ }
+ }
+ if ( NULL == pAllocator )
+ {
+ DefaultDeallocator( p );
+ return;
+ }
+
+ assert( NULL != chunk );
+ const bool found = pAllocator->Deallocate( p, chunk );
+ (void) found;
+ assert( found );
+}
+
+// SmallObjAllocator::IsCorrupt -----------------------------------------------
+
+bool SmallObjAllocator::IsCorrupt( void ) const
+{
+ if ( NULL == pool_ )
+ {
+ assert( false );
+ return true;
+ }
+ if ( 0 == GetAlignment() )
+ {
+ assert( false );
+ return true;
+ }
+ if ( 0 == GetMaxObjectSize() )
+ {
+ assert( false );
+ return true;
+ }
+ const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
+ for ( std::size_t ii = 0; ii < allocCount; ++ii )
+ {
+ if ( pool_[ ii ].IsCorrupt() )
+ return true;
+ }
+ return false;
+}
+
+} // end namespace Loki
+
diff --git a/shared/loki/SmallObj.h b/shared/loki/SmallObj.h
new file mode 100644
index 00000000..65828bf2
--- /dev/null
+++ b/shared/loki/SmallObj.h
@@ -0,0 +1,644 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_SMALLOBJ_INC_
+#define LOKI_SMALLOBJ_INC_
+
+// $Id: SmallObj.h 806 2007-02-03 00:01:52Z rich_sposato $
+
+
+#include "LokiExport.h"
+#include "Threads.h"
+#include "Singleton.h"
+#include <cstddef>
+#include <new> // needed for std::nothrow_t parameter.
+
+#ifndef LOKI_DEFAULT_CHUNK_SIZE
+#define LOKI_DEFAULT_CHUNK_SIZE 4096
+#endif
+
+#ifndef LOKI_MAX_SMALL_OBJECT_SIZE
+#define LOKI_MAX_SMALL_OBJECT_SIZE 256
+#endif
+
+#ifndef LOKI_DEFAULT_OBJECT_ALIGNMENT
+#define LOKI_DEFAULT_OBJECT_ALIGNMENT 4
+#endif
+
+#ifndef LOKI_DEFAULT_SMALLOBJ_LIFETIME
+#define LOKI_DEFAULT_SMALLOBJ_LIFETIME ::Loki::LongevityLifetime::DieAsSmallObjectParent
+#endif
+
+#if defined(LOKI_SMALL_OBJECT_USE_NEW_ARRAY) && defined(_MSC_VER)
+#pragma message("Don't define LOKI_SMALL_OBJECT_USE_NEW_ARRAY when using a Microsoft compiler to prevent memory leaks.")
+#pragma message("now calling '#undef LOKI_SMALL_OBJECT_USE_NEW_ARRAY'")
+#undef LOKI_SMALL_OBJECT_USE_NEW_ARRAY
+#endif
+
+/// \defgroup SmallObjectGroup Small objects
+///
+/// \defgroup SmallObjectGroupInternal Internals
+/// \ingroup SmallObjectGroup
+
+namespace Loki
+{
+ namespace LongevityLifetime
+ {
+ /** @struct DieAsSmallObjectParent
+ @ingroup SmallObjectGroup
+ Lifetime policy to manage lifetime dependencies of
+ SmallObject base and child classes.
+ The Base class should have this lifetime
+ */
+ template <class T>
+ struct DieAsSmallObjectParent : DieLast<T> {};
+
+ /** @struct DieAsSmallObjectChild
+ @ingroup SmallObjectGroup
+ Lifetime policy to manage lifetime dependencies of
+ SmallObject base and child classes.
+ The Child class should have this lifetime
+ */
+ template <class T>
+ struct DieAsSmallObjectChild : DieDirectlyBeforeLast<T> {};
+
+ }
+
+ class FixedAllocator;
+
+ /** @class SmallObjAllocator
+ @ingroup SmallObjectGroupInternal
+ Manages pool of fixed-size allocators.
+ Designed to be a non-templated base class of AllocatorSingleton so that
+ implementation details can be safely hidden in the source code file.
+ */
+ class LOKI_EXPORT SmallObjAllocator
+ {
+ protected:
+ /** The only available constructor needs certain parameters in order to
+ initialize all the FixedAllocator's. This throws only if
+ @param pageSize # of bytes in a page of memory.
+ @param maxObjectSize Max # of bytes which this may allocate.
+ @param objectAlignSize # of bytes between alignment boundaries.
+ */
+ SmallObjAllocator( std::size_t pageSize, std::size_t maxObjectSize,
+ std::size_t objectAlignSize );
+
+ /** Destructor releases all blocks, all Chunks, and FixedAllocator's.
+ Any outstanding blocks are unavailable, and should not be used after
+ this destructor is called. The destructor is deliberately non-virtual
+ because it is protected, not public.
+ */
+ ~SmallObjAllocator( void );
+
+ public:
+ /** Allocates a block of memory of requested size. Complexity is often
+ constant-time, but might be O(C) where C is the number of Chunks in a
+ FixedAllocator.
+
+ @par Exception Safety Level
+ Provides either strong-exception safety, or no-throw exception-safety
+ level depending upon doThrow parameter. The reason it provides two
+ levels of exception safety is because it is used by both the nothrow
+ and throwing new operators. The underlying implementation will never
+ throw of its own accord, but this can decide to throw if it does not
+ allocate. The only exception it should emit is std::bad_alloc.
+
+ @par Allocation Failure
+ If it does not allocate, it will call TrimExcessMemory and attempt to
+ allocate again, before it decides to throw or return NULL. Many
+ allocators loop through several new_handler functions, and terminate
+ if they can not allocate, but not this one. It only makes one attempt
+ using its own implementation of the new_handler, and then returns NULL
+ or throws so that the program can decide what to do at a higher level.
+ (Side note: Even though the C++ Standard allows allocators and
+ new_handlers to terminate if they fail, the Loki allocator does not do
+ that since that policy is not polite to a host program.)
+
+ @param size # of bytes needed for allocation.
+ @param doThrow True if this should throw if unable to allocate, false
+ if it should provide no-throw exception safety level.
+ @return NULL if nothing allocated and doThrow is false. Else the
+ pointer to an available block of memory.
+ */
+ void * Allocate( std::size_t size, bool doThrow );
+
+ /** Deallocates a block of memory at a given place and of a specific
+ size. Complexity is almost always constant-time, and is O(C) only if
+ it has to search for which Chunk deallocates. This never throws.
+ */
+ void Deallocate( void * p, std::size_t size );
+
+ /** Deallocates a block of memory at a given place but of unknown size
+ size. Complexity is O(F + C) where F is the count of FixedAllocator's
+ in the pool, and C is the number of Chunks in all FixedAllocator's. This
+ does not throw exceptions. This overloaded version of Deallocate is
+ called by the nothow delete operator - which is called when the nothrow
+ new operator is used, but a constructor throws an exception.
+ */
+ void Deallocate( void * p );
+
+ /// Returns max # of bytes which this can allocate.
+ inline std::size_t GetMaxObjectSize() const
+ { return maxSmallObjectSize_; }
+
+ /// Returns # of bytes between allocation boundaries.
+ inline std::size_t GetAlignment() const { return objectAlignSize_; }
+
+ /** Releases empty Chunks from memory. Complexity is O(F + C) where F
+ is the count of FixedAllocator's in the pool, and C is the number of
+ Chunks in all FixedAllocator's. This will never throw. This is called
+ by AllocatorSingleto::ClearExtraMemory, the new_handler function for
+ Loki's allocator, and is called internally when an allocation fails.
+ @return True if any memory released, or false if none released.
+ */
+ bool TrimExcessMemory( void );
+
+ /** Returns true if anything in implementation is corrupt. Complexity
+ is O(F + C + B) where F is the count of FixedAllocator's in the pool,
+ C is the number of Chunks in all FixedAllocator's, and B is the number
+ of blocks in all Chunks. If it determines any data is corrupted, this
+ will return true in release version, but assert in debug version at
+ the line where it detects the corrupted data. If it does not detect
+ any corrupted data, it returns false.
+ */
+ bool IsCorrupt( void ) const;
+
+ private:
+ /// Default-constructor is not implemented.
+ SmallObjAllocator( void );
+ /// Copy-constructor is not implemented.
+ SmallObjAllocator( const SmallObjAllocator & );
+ /// Copy-assignment operator is not implemented.
+ SmallObjAllocator & operator = ( const SmallObjAllocator & );
+
+ /// Pointer to array of fixed-size allocators.
+ Loki::FixedAllocator * pool_;
+
+ /// Largest object size supported by allocators.
+ const std::size_t maxSmallObjectSize_;
+
+ /// Size of alignment boundaries.
+ const std::size_t objectAlignSize_;
+ };
+
+
+ /** @class AllocatorSingleton
+ @ingroup SmallObjectGroupInternal
+ This template class is derived from
+ SmallObjAllocator in order to pass template arguments into it, and still
+ have a default constructor for the singleton. Each instance is a unique
+ combination of all the template parameters, and hence is singleton only
+ with respect to those parameters. The template parameters have default
+ values and the class has typedefs identical to both SmallObject and
+ SmallValueObject so that this class can be used directly instead of going
+ through SmallObject or SmallValueObject. That design feature allows
+ clients to use the new_handler without having the name of the new_handler
+ function show up in classes derived from SmallObject or SmallValueObject.
+ Thus, the only functions in the allocator which show up in SmallObject or
+ SmallValueObject inheritance hierarchies are the new and delete
+ operators.
+ */
+ template
+ <
+ template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
+ std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE,
+ std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE,
+ std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT,
+ template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME,
+ class MutexPolicy = LOKI_DEFAULT_MUTEX
+ >
+ class AllocatorSingleton : public SmallObjAllocator
+ {
+ public:
+
+ /// Defines type of allocator.
+ typedef AllocatorSingleton< ThreadingModel, chunkSize,
+ maxSmallObjectSize, objectAlignSize, LifetimePolicy > MyAllocator;
+
+ /// Defines type for thread-safety locking mechanism.
+ typedef ThreadingModel< MyAllocator, MutexPolicy > MyThreadingModel;
+
+ /// Defines singleton made from allocator.
+ typedef Loki::SingletonHolder< MyAllocator, Loki::CreateStatic,
+ LifetimePolicy, ThreadingModel > MyAllocatorSingleton;
+
+ /// Returns reference to the singleton.
+ inline static AllocatorSingleton & Instance( void )
+ {
+ return MyAllocatorSingleton::Instance();
+ }
+
+ /// The default constructor is not meant to be called directly.
+ inline AllocatorSingleton() :
+ SmallObjAllocator( chunkSize, maxSmallObjectSize, objectAlignSize )
+ {}
+
+ /// The destructor is not meant to be called directly.
+ inline ~AllocatorSingleton( void ) {}
+
+ /** Clears any excess memory used by the allocator. Complexity is
+ O(F + C) where F is the count of FixedAllocator's in the pool, and C
+ is the number of Chunks in all FixedAllocator's. This never throws.
+ @note This function can be used as a new_handler when Loki and other
+ memory allocators can no longer allocate. Although the C++ Standard
+ allows new_handler functions to terminate the program when they can
+ not release any memory, this will not do so.
+ */
+ static void ClearExtraMemory( void );
+
+ /** Returns true if anything in implementation is corrupt. Complexity
+ is O(F + C + B) where F is the count of FixedAllocator's in the pool,
+ C is the number of Chunks in all FixedAllocator's, and B is the number
+ of blocks in all Chunks. If it determines any data is corrupted, this
+ will return true in release version, but assert in debug version at
+ the line where it detects the corrupted data. If it does not detect
+ any corrupted data, it returns false.
+ */
+ static bool IsCorrupted( void );
+
+ private:
+ /// Copy-constructor is not implemented.
+ AllocatorSingleton( const AllocatorSingleton & );
+ /// Copy-assignment operator is not implemented.
+ AllocatorSingleton & operator = ( const AllocatorSingleton & );
+ };
+
+ template
+ <
+ template <class, class> class T,
+ std::size_t C,
+ std::size_t M,
+ std::size_t O,
+ template <class> class L,
+ class X
+ >
+ void AllocatorSingleton< T, C, M, O, L, X >::ClearExtraMemory( void )
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ Instance().TrimExcessMemory();
+ }
+
+ template
+ <
+ template <class, class> class T,
+ std::size_t C,
+ std::size_t M,
+ std::size_t O,
+ template <class> class L,
+ class X
+ >
+ bool AllocatorSingleton< T, C, M, O, L, X >::IsCorrupted( void )
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ return Instance().IsCorrupt();
+ }
+
+ /** This standalone function provides the longevity level for Small-Object
+ Allocators which use the Loki::SingletonWithLongevity policy. The
+ SingletonWithLongevity class can find this function through argument-
+ dependent lookup.
+
+ @par Longevity Levels
+ No Small-Object Allocator depends on any other Small-Object allocator, so
+ this does not need to calculate dependency levels among allocators, and
+ it returns just a constant. All allocators must live longer than the
+ objects which use the allocators, it must return a longevity level higher
+ than any such object.
+ */
+ template
+ <
+ template <class, class> class T,
+ std::size_t C,
+ std::size_t M,
+ std::size_t O,
+ template <class> class L,
+ class X
+ >
+ inline unsigned int GetLongevity(
+ AllocatorSingleton< T, C, M, O, L, X > * )
+ {
+ // Returns highest possible value.
+ return 0xFFFFFFFF;
+ }
+
+
+ /** @class SmallObjectBase
+ @ingroup SmallObjectGroup
+ Base class for small object allocation classes.
+ The shared implementation of the new and delete operators are here instead
+ of being duplicated in both SmallObject or SmallValueObject, later just
+ called Small-Objects. This class is not meant to be used directly by clients,
+ or derived from by clients. Class has no data members so compilers can
+ use Empty-Base-Optimization.
+
+ @par ThreadingModel
+ This class doesn't support ObjectLevelLockable policy for ThreadingModel.
+ The allocator is a singleton, so a per-instance mutex is not necessary.
+ Nor is using ObjectLevelLockable recommended with SingletonHolder since
+ the SingletonHolder::MakeInstance function requires a mutex that exists
+ prior to when the object is created - which is not possible if the mutex
+ is inside the object, such as required for ObjectLevelLockable. If you
+ attempt to use ObjectLevelLockable, the compiler will emit errors because
+ it can't use the default constructor in ObjectLevelLockable. If you need
+ a thread-safe allocator, use the ClassLevelLockable policy.
+
+ @par Lifetime Policy
+
+ The SmallObjectBase template needs a lifetime policy because it owns
+ a singleton of SmallObjAllocator which does all the low level functions.
+ When using a Small-Object in combination with the SingletonHolder template
+ you have to choose two lifetimes, that of the Small-Object and that of
+ the singleton. The rule is: The Small-Object lifetime must be greater than
+ the lifetime of the singleton hosting the Small-Object. Violating this rule
+ results in a crash on exit, because the hosting singleton tries to delete
+ the Small-Object which is then already destroyed.
+
+ The lifetime policies recommended for use with Small-Objects hosted
+ by a SingletonHolder template are
+ - LongevityLifetime::DieAsSmallObjectParent / LongevityLifetime::DieAsSmallObjectChild
+ - SingletonWithLongevity
+ - FollowIntoDeath (not supported by MSVC 7.1)
+ - NoDestroy
+
+ The default lifetime of Small-Objects is
+ LongevityLifetime::DieAsSmallObjectParent to
+ insure that memory is not released before a object with the lifetime
+ LongevityLifetime::DieAsSmallObjectChild using that
+ memory is destroyed. The LongevityLifetime::DieAsSmallObjectParent
+ lifetime has the highest possible value of a SetLongevity lifetime, so
+ you can use it in combination with your own lifetime not having also
+ the highest possible value.
+
+ The DefaultLifetime and PhoenixSingleton policies are *not* recommended
+ since they can cause the allocator to be destroyed and release memory
+ for singletons hosting a object which inherit from either SmallObject
+ or SmallValueObject.
+
+ @par Lifetime usage
+
+ - LongevityLifetime: The Small-Object has
+ LongevityLifetime::DieAsSmallObjectParent policy and the Singleton
+ hosting the Small-Object has LongevityLifetime::DieAsSmallObjectChild.
+ The child lifetime has a hard coded SetLongevity lifetime which is
+ shorter than the lifetime of the parent, thus the child dies
+ before the parent.
+
+ - Both Small-Object and Singleton use SingletonWithLongevity policy.
+ The longevity level for the singleton must be lower than that for the
+ Small-Object. This is why the AllocatorSingleton's GetLongevity function
+ returns the highest value.
+
+ - FollowIntoDeath lifetime: The Small-Object has
+ FollowIntoDeath::With<LIFETIME>::AsMasterLiftime
+ policy and the Singleton has
+ FollowIntoDeath::AfterMaster<MASTERSINGLETON>::IsDestroyed policy,
+ where you could choose the LIFETIME.
+
+ - Both Small-Object and Singleton use NoDestroy policy.
+ Since neither is ever destroyed, the destruction order does not matter.
+ Note: you will get memory leaks!
+
+ - The Small-Object has NoDestroy policy but the Singleton has
+ SingletonWithLongevity policy. Note: you will get memory leaks!
+
+
+ You should *not* use NoDestroy for the singleton, and then use
+ SingletonWithLongevity for the Small-Object.
+
+ @par Examples:
+
+ - test/SmallObj/SmallSingleton.cpp
+ - test/Singleton/Dependencies.cpp
+ */
+ template
+ <
+ template <class, class> class ThreadingModel,
+ std::size_t chunkSize,
+ std::size_t maxSmallObjectSize,
+ std::size_t objectAlignSize,
+ template <class> class LifetimePolicy,
+ class MutexPolicy
+ >
+ class SmallObjectBase
+ {
+
+#if (LOKI_MAX_SMALL_OBJECT_SIZE != 0) && (LOKI_DEFAULT_CHUNK_SIZE != 0) && (LOKI_DEFAULT_OBJECT_ALIGNMENT != 0)
+
+ public:
+ /// Defines type of allocator singleton, must be public
+ /// to handle singleton lifetime dependencies.
+ typedef AllocatorSingleton< ThreadingModel, chunkSize,
+ maxSmallObjectSize, objectAlignSize, LifetimePolicy > ObjAllocatorSingleton;
+
+ private:
+
+ /// Defines type for thread-safety locking mechanism.
+ typedef ThreadingModel< ObjAllocatorSingleton, MutexPolicy > MyThreadingModel;
+
+ /// Use singleton defined in AllocatorSingleton.
+ typedef typename ObjAllocatorSingleton::MyAllocatorSingleton MyAllocatorSingleton;
+
+ public:
+
+ /// Throwing single-object new throws bad_alloc when allocation fails.
+#ifdef _MSC_VER
+ /// @note MSVC complains about non-empty exception specification lists.
+ static void * operator new ( std::size_t size )
+#else
+ static void * operator new ( std::size_t size ) throw ( std::bad_alloc )
+#endif
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ return MyAllocatorSingleton::Instance().Allocate( size, true );
+ }
+
+ /// Non-throwing single-object new returns NULL if allocation fails.
+ static void * operator new ( std::size_t size, const std::nothrow_t & ) throw ()
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ return MyAllocatorSingleton::Instance().Allocate( size, false );
+ }
+
+ /// Placement single-object new merely calls global placement new.
+ inline static void * operator new ( std::size_t size, void * place )
+ {
+ return ::operator new( size, place );
+ }
+
+ /// Single-object delete.
+ static void operator delete ( void * p, std::size_t size ) throw ()
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ MyAllocatorSingleton::Instance().Deallocate( p, size );
+ }
+
+ /** Non-throwing single-object delete is only called when nothrow
+ new operator is used, and the constructor throws an exception.
+ */
+ static void operator delete ( void * p, const std::nothrow_t & ) throw()
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ MyAllocatorSingleton::Instance().Deallocate( p );
+ }
+
+ /// Placement single-object delete merely calls global placement delete.
+ inline static void operator delete ( void * p, void * place )
+ {
+ ::operator delete ( p, place );
+ }
+
+#ifdef LOKI_SMALL_OBJECT_USE_NEW_ARRAY
+
+ /// Throwing array-object new throws bad_alloc when allocation fails.
+#ifdef _MSC_VER
+ /// @note MSVC complains about non-empty exception specification lists.
+ static void * operator new [] ( std::size_t size )
+#else
+ static void * operator new [] ( std::size_t size )
+ throw ( std::bad_alloc )
+#endif
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ return MyAllocatorSingleton::Instance().Allocate( size, true );
+ }
+
+ /// Non-throwing array-object new returns NULL if allocation fails.
+ static void * operator new [] ( std::size_t size,
+ const std::nothrow_t & ) throw ()
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ return MyAllocatorSingleton::Instance().Allocate( size, false );
+ }
+
+ /// Placement array-object new merely calls global placement new.
+ inline static void * operator new [] ( std::size_t size, void * place )
+ {
+ return ::operator new( size, place );
+ }
+
+ /// Array-object delete.
+ static void operator delete [] ( void * p, std::size_t size ) throw ()
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ MyAllocatorSingleton::Instance().Deallocate( p, size );
+ }
+
+ /** Non-throwing array-object delete is only called when nothrow
+ new operator is used, and the constructor throws an exception.
+ */
+ static void operator delete [] ( void * p,
+ const std::nothrow_t & ) throw()
+ {
+ typename MyThreadingModel::Lock lock;
+ (void)lock; // get rid of warning
+ MyAllocatorSingleton::Instance().Deallocate( p );
+ }
+
+ /// Placement array-object delete merely calls global placement delete.
+ inline static void operator delete [] ( void * p, void * place )
+ {
+ ::operator delete ( p, place );
+ }
+#endif // #if use new array functions.
+
+#endif // #if default template parameters are not zero
+
+ protected:
+ inline SmallObjectBase( void ) {}
+ inline SmallObjectBase( const SmallObjectBase & ) {}
+ inline SmallObjectBase & operator = ( const SmallObjectBase & )
+ { return *this; }
+ inline ~SmallObjectBase() {}
+ }; // end class SmallObjectBase
+
+
+ /** @class SmallObject
+ @ingroup SmallObjectGroup
+ SmallObject Base class for polymorphic small objects, offers fast
+ allocations & deallocations. Destructor is virtual and public. Default
+ constructor is trivial. Copy-constructor and copy-assignment operator are
+ not implemented since polymorphic classes almost always disable those
+ operations. Class has no data members so compilers can use
+ Empty-Base-Optimization.
+ */
+ template
+ <
+ template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
+ std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE,
+ std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE,
+ std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT,
+ template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME,
+ class MutexPolicy = LOKI_DEFAULT_MUTEX
+ >
+ class SmallObject : public SmallObjectBase< ThreadingModel, chunkSize,
+ maxSmallObjectSize, objectAlignSize, LifetimePolicy, MutexPolicy >
+ {
+
+ public:
+ virtual ~SmallObject() {}
+ protected:
+ inline SmallObject( void ) {}
+
+ private:
+ /// Copy-constructor is not implemented.
+ SmallObject( const SmallObject & );
+ /// Copy-assignment operator is not implemented.
+ SmallObject & operator = ( const SmallObject & );
+ }; // end class SmallObject
+
+
+ /** @class SmallValueObject
+ @ingroup SmallObjectGroup
+ SmallValueObject Base class for small objects with value-type
+ semantics - offers fast allocations & deallocations. Destructor is
+ non-virtual, inline, and protected to prevent unintentional destruction
+ through base class. Default constructor is trivial. Copy-constructor
+ and copy-assignment operator are trivial since value-types almost always
+ need those operations. Class has no data members so compilers can use
+ Empty-Base-Optimization.
+ */
+ template
+ <
+ template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
+ std::size_t chunkSize = LOKI_DEFAULT_CHUNK_SIZE,
+ std::size_t maxSmallObjectSize = LOKI_MAX_SMALL_OBJECT_SIZE,
+ std::size_t objectAlignSize = LOKI_DEFAULT_OBJECT_ALIGNMENT,
+ template <class> class LifetimePolicy = LOKI_DEFAULT_SMALLOBJ_LIFETIME,
+ class MutexPolicy = LOKI_DEFAULT_MUTEX
+ >
+ class SmallValueObject : public SmallObjectBase< ThreadingModel, chunkSize,
+ maxSmallObjectSize, objectAlignSize, LifetimePolicy, MutexPolicy >
+ {
+ protected:
+ inline SmallValueObject( void ) {}
+ inline SmallValueObject( const SmallValueObject & ) {}
+ inline SmallValueObject & operator = ( const SmallValueObject & )
+ { return *this; }
+ inline ~SmallValueObject() {}
+ }; // end class SmallValueObject
+
+} // namespace Loki
+
+#endif // end file guardian
+
diff --git a/shared/loki/SmartPtr.h b/shared/loki/SmartPtr.h
new file mode 100644
index 00000000..df548553
--- /dev/null
+++ b/shared/loki/SmartPtr.h
@@ -0,0 +1,1778 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_SMARTPTR_INC_
+#define LOKI_SMARTPTR_INC_
+
+// $Id: SmartPtr.h 903 2008-11-10 05:55:12Z rich_sposato $
+
+
+/// \defgroup SmartPointerGroup Smart pointers
+/// Policy based implementation of a smart pointer
+/// \defgroup SmartPointerOwnershipGroup Ownership policies
+/// \ingroup SmartPointerGroup
+/// \defgroup SmartPointerStorageGroup Storage policies
+/// \ingroup SmartPointerGroup
+/// \defgroup SmartPointerConversionGroup Conversion policies
+/// \ingroup SmartPointerGroup
+/// \defgroup SmartPointerCheckingGroup Checking policies
+/// \ingroup SmartPointerGroup
+
+#include "LokiExport.h"
+#include "SmallObj.h"
+#include "TypeManip.h"
+#include "static_check.h"
+#include "RefToValue.h"
+#include "ConstPolicy.h"
+
+#include <functional>
+#include <stdexcept>
+#include <cassert>
+#include <string>
+
+#if !defined(_MSC_VER)
+# if defined(__sparc__)
+# include <inttypes.h>
+# else
+# include <stdint.h>
+# endif
+#endif
+
+#if defined(_MSC_VER) || defined(__GNUC__)
+// GCC>=4.1 must use -ffriend-injection due to a bug in GCC
+#define LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
+#endif
+
+
+namespace Loki
+{
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class HeapStorage
+///
+/// \ingroup SmartPointerStorageGroup
+/// Implementation of the StoragePolicy used by SmartPtr. Uses explicit call
+/// to T's destructor followed by call to free.
+////////////////////////////////////////////////////////////////////////////////
+
+
+ template <class T>
+ class HeapStorage
+ {
+ public:
+ typedef T* StoredType; /// the type of the pointee_ object
+ typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
+ typedef T* PointerType; /// type returned by operator->
+ typedef T& ReferenceType; /// type returned by operator*
+
+ HeapStorage() : pointee_(Default())
+ {}
+
+ // The storage policy doesn't initialize the stored pointer
+ // which will be initialized by the OwnershipPolicy's Clone fn
+ HeapStorage(const HeapStorage&) : pointee_(0)
+ {}
+
+ template <class U>
+ HeapStorage(const HeapStorage<U>&) : pointee_(0)
+ {}
+
+ HeapStorage(const StoredType& p) : pointee_(p) {}
+
+ PointerType operator->() const { return pointee_; }
+
+ ReferenceType operator*() const { return *pointee_; }
+
+ void Swap(HeapStorage& rhs)
+ { std::swap(pointee_, rhs.pointee_); }
+
+ // Accessors
+ template <class F>
+ friend typename HeapStorage<F>::PointerType GetImpl(const HeapStorage<F>& sp);
+
+ template <class F>
+ friend const typename HeapStorage<F>::StoredType& GetImplRef(const HeapStorage<F>& sp);
+
+ template <class F>
+ friend typename HeapStorage<F>::StoredType& GetImplRef(HeapStorage<F>& sp);
+
+ protected:
+ // Destroys the data stored
+ // (Destruction might be taken over by the OwnershipPolicy)
+ void Destroy()
+ {
+ if ( 0 != pointee_ )
+ {
+ pointee_->~T();
+ ::free( pointee_ );
+ }
+ }
+
+ // Default value to initialize the pointer
+ static StoredType Default()
+ { return 0; }
+
+ private:
+ // Data
+ StoredType pointee_;
+ };
+
+ template <class T>
+ inline typename HeapStorage<T>::PointerType GetImpl(const HeapStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline const typename HeapStorage<T>::StoredType& GetImplRef(const HeapStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline typename HeapStorage<T>::StoredType& GetImplRef(HeapStorage<T>& sp)
+ { return sp.pointee_; }
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class DefaultSPStorage
+///
+/// \ingroup SmartPointerStorageGroup
+/// Implementation of the StoragePolicy used by SmartPtr
+////////////////////////////////////////////////////////////////////////////////
+
+
+ template <class T>
+ class DefaultSPStorage
+ {
+ public:
+ typedef T* StoredType; // the type of the pointee_ object
+ typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
+ typedef T* PointerType; // type returned by operator->
+ typedef T& ReferenceType; // type returned by operator*
+
+ DefaultSPStorage() : pointee_(Default())
+ {}
+
+ // The storage policy doesn't initialize the stored pointer
+ // which will be initialized by the OwnershipPolicy's Clone fn
+ DefaultSPStorage(const DefaultSPStorage&) : pointee_(0)
+ {}
+
+ template <class U>
+ DefaultSPStorage(const DefaultSPStorage<U>&) : pointee_(0)
+ {}
+
+ DefaultSPStorage(const StoredType& p) : pointee_(p) {}
+
+ PointerType operator->() const { return pointee_; }
+
+ ReferenceType operator*() const { return *pointee_; }
+
+ void Swap(DefaultSPStorage& rhs)
+ { std::swap(pointee_, rhs.pointee_); }
+
+ // Accessors
+ template <class F>
+ friend typename DefaultSPStorage<F>::PointerType GetImpl(const DefaultSPStorage<F>& sp);
+
+ template <class F>
+ friend const typename DefaultSPStorage<F>::StoredType& GetImplRef(const DefaultSPStorage<F>& sp);
+
+ template <class F>
+ friend typename DefaultSPStorage<F>::StoredType& GetImplRef(DefaultSPStorage<F>& sp);
+
+ protected:
+ // Destroys the data stored
+ // (Destruction might be taken over by the OwnershipPolicy)
+ //
+ // If your compiler gives you a warning in this area while
+ // compiling the tests, it is on purpose, please ignore it.
+ void Destroy()
+ {
+ delete pointee_;
+ }
+
+ // Default value to initialize the pointer
+ static StoredType Default()
+ { return 0; }
+
+ private:
+ // Data
+ StoredType pointee_;
+ };
+
+ template <class T>
+ inline typename DefaultSPStorage<T>::PointerType GetImpl(const DefaultSPStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline const typename DefaultSPStorage<T>::StoredType& GetImplRef(const DefaultSPStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline typename DefaultSPStorage<T>::StoredType& GetImplRef(DefaultSPStorage<T>& sp)
+ { return sp.pointee_; }
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class LockedStorage
+///
+/// \ingroup SmartPointerStorageGroup
+/// Implementation of the StoragePolicy used by SmartPtr.
+///
+/// Each call to operator-> locks the object for the duration of a call to a
+/// member function of T.
+///
+/// \par How It Works
+/// LockedStorage has a helper class called Locker, which acts as a smart
+/// pointer with limited abilities. LockedStorage::operator-> returns an
+/// unnamed temporary of type Locker<T> that exists for the duration of the
+/// call to a member function of T. The unnamed temporary locks the object
+/// when it is constructed by operator-> and unlocks the object when it is
+/// destructed.
+///
+/// \note This storage policy requires class T to have member functions Lock
+/// and Unlock. If your class does not have Lock or Unlock functions, you may
+/// either make a child class which does, or make a policy class similar to
+/// LockedStorage which calls other functions to lock the object.
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class Locker
+ {
+ public:
+ Locker( const T * p ) : pointee_( const_cast< T * >( p ) )
+ {
+ if ( pointee_ != 0 )
+ pointee_->Lock();
+ }
+
+ ~Locker( void )
+ {
+ if ( pointee_ != 0 )
+ pointee_->Unlock();
+ }
+
+ operator T * ()
+ {
+ return pointee_;
+ }
+
+ T * operator->()
+ {
+ return pointee_;
+ }
+
+ private:
+ Locker( void );
+ Locker & operator = ( const Locker & );
+ T * pointee_;
+ };
+
+ template <class T>
+ class LockedStorage
+ {
+ public:
+
+ typedef T* StoredType; /// the type of the pointee_ object
+ typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
+ typedef Locker< T > PointerType; /// type returned by operator->
+ typedef T& ReferenceType; /// type returned by operator*
+
+ LockedStorage() : pointee_( Default() ) {}
+
+ ~LockedStorage( void ) {}
+
+ LockedStorage( const LockedStorage&) : pointee_( 0 ) {}
+
+ LockedStorage( const StoredType & p ) : pointee_( p ) {}
+
+ PointerType operator->()
+ {
+ return Locker< T >( pointee_ );
+ }
+
+ void Swap(LockedStorage& rhs)
+ {
+ std::swap( pointee_, rhs.pointee_ );
+ }
+
+ // Accessors
+ template <class F>
+ friend typename LockedStorage<F>::InitPointerType GetImpl(const LockedStorage<F>& sp);
+
+ template <class F>
+ friend const typename LockedStorage<F>::StoredType& GetImplRef(const LockedStorage<F>& sp);
+
+ template <class F>
+ friend typename LockedStorage<F>::StoredType& GetImplRef(LockedStorage<F>& sp);
+
+ protected:
+ // Destroys the data stored
+ // (Destruction might be taken over by the OwnershipPolicy)
+ void Destroy()
+ {
+ delete pointee_;
+ }
+
+ // Default value to initialize the pointer
+ static StoredType Default()
+ { return 0; }
+
+ private:
+ /// Dereference operator is not implemented.
+ ReferenceType operator*();
+
+ // Data
+ StoredType pointee_;
+ };
+
+ template <class T>
+ inline typename LockedStorage<T>::InitPointerType GetImpl(const LockedStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline const typename LockedStorage<T>::StoredType& GetImplRef(const LockedStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline typename LockedStorage<T>::StoredType& GetImplRef(LockedStorage<T>& sp)
+ { return sp.pointee_; }
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class ArrayStorage
+///
+/// \ingroup SmartPointerStorageGroup
+/// Implementation of the ArrayStorage used by SmartPtr
+////////////////////////////////////////////////////////////////////////////////
+
+
+ template <class T>
+ class ArrayStorage
+ {
+ public:
+ typedef T* StoredType; // the type of the pointee_ object
+ typedef T* InitPointerType; /// type used to declare OwnershipPolicy type.
+ typedef T* PointerType; // type returned by operator->
+ typedef T& ReferenceType; // type returned by operator*
+
+ ArrayStorage() : pointee_(Default())
+ {}
+
+ // The storage policy doesn't initialize the stored pointer
+ // which will be initialized by the OwnershipPolicy's Clone fn
+ ArrayStorage(const ArrayStorage&) : pointee_(0)
+ {}
+
+ template <class U>
+ ArrayStorage(const ArrayStorage<U>&) : pointee_(0)
+ {}
+
+ ArrayStorage(const StoredType& p) : pointee_(p) {}
+
+ PointerType operator->() const { return pointee_; }
+
+ ReferenceType operator*() const { return *pointee_; }
+
+ void Swap(ArrayStorage& rhs)
+ { std::swap(pointee_, rhs.pointee_); }
+
+ // Accessors
+ template <class F>
+ friend typename ArrayStorage<F>::PointerType GetImpl(const ArrayStorage<F>& sp);
+
+ template <class F>
+ friend const typename ArrayStorage<F>::StoredType& GetImplRef(const ArrayStorage<F>& sp);
+
+ template <class F>
+ friend typename ArrayStorage<F>::StoredType& GetImplRef(ArrayStorage<F>& sp);
+
+ protected:
+ // Destroys the data stored
+ // (Destruction might be taken over by the OwnershipPolicy)
+ void Destroy()
+ { delete [] pointee_; }
+
+ // Default value to initialize the pointer
+ static StoredType Default()
+ { return 0; }
+
+ private:
+ // Data
+ StoredType pointee_;
+ };
+
+ template <class T>
+ inline typename ArrayStorage<T>::PointerType GetImpl(const ArrayStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline const typename ArrayStorage<T>::StoredType& GetImplRef(const ArrayStorage<T>& sp)
+ { return sp.pointee_; }
+
+ template <class T>
+ inline typename ArrayStorage<T>::StoredType& GetImplRef(ArrayStorage<T>& sp)
+ { return sp.pointee_; }
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class RefCounted
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Provides a classic external reference counting implementation
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ class RefCounted
+ {
+ public:
+ RefCounted()
+ : pCount_(static_cast<uintptr_t*>(
+ SmallObject<>::operator new(sizeof(uintptr_t))))
+ {
+ assert(pCount_!=0);
+ *pCount_ = 1;
+ }
+
+ RefCounted(const RefCounted& rhs)
+ : pCount_(rhs.pCount_)
+ {}
+
+ // MWCW lacks template friends, hence the following kludge
+ template <typename P1>
+ RefCounted(const RefCounted<P1>& rhs)
+ : pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
+ {}
+
+ P Clone(const P& val)
+ {
+ ++*pCount_;
+ return val;
+ }
+
+ bool Release(const P&)
+ {
+ if (!--*pCount_)
+ {
+ SmallObject<>::operator delete(pCount_, sizeof(uintptr_t));
+ pCount_ = NULL;
+ return true;
+ }
+ return false;
+ }
+
+ void Swap(RefCounted& rhs)
+ { std::swap(pCount_, rhs.pCount_); }
+
+ enum { destructiveCopy = false };
+
+ private:
+ // Data
+ uintptr_t* pCount_;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct RefCountedMT
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements external reference counting for multithreaded programs
+/// Policy Usage: RefCountedMTAdj<ThreadingModel>::RefCountedMT
+///
+/// \par Warning
+/// There could be a race condition, see bug "Race condition in RefCountedMTAdj::Release"
+/// http://sourceforge.net/tracker/index.php?func=detail&aid=1408845&group_id=29557&atid=396644
+/// As stated in bug 1408845, the Release function is not thread safe if a
+/// SmartPtr copy-constructor tries to copy the last pointer to an object in
+/// one thread, while the destructor is acting on the last pointer in another
+/// thread. The existence of a race between a copy-constructor and destructor
+/// implies a design flaw at a higher level. That race condition must be
+/// fixed at a higher design level, and no change to this class could fix it.
+////////////////////////////////////////////////////////////////////////////////
+
+ template <template <class, class> class ThreadingModel,
+ class MX = LOKI_DEFAULT_MUTEX >
+ struct RefCountedMTAdj
+ {
+ template <class P>
+ class RefCountedMT : public ThreadingModel< RefCountedMT<P>, MX >
+ {
+ typedef ThreadingModel< RefCountedMT<P>, MX > base_type;
+ typedef typename base_type::IntType CountType;
+ typedef volatile CountType *CountPtrType;
+
+ public:
+ RefCountedMT()
+ {
+ pCount_ = static_cast<CountPtrType>(
+ SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator new(
+ sizeof(*pCount_)));
+ assert(pCount_);
+ //*pCount_ = 1;
+ ThreadingModel<RefCountedMT, MX>::AtomicAssign(*pCount_, 1);
+ }
+
+ RefCountedMT(const RefCountedMT& rhs)
+ : pCount_(rhs.pCount_)
+ {}
+
+ //MWCW lacks template friends, hence the following kludge
+ template <typename P1>
+ RefCountedMT(const RefCountedMT<P1>& rhs)
+ : pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_)
+ {}
+
+ P Clone(const P& val)
+ {
+ ThreadingModel<RefCountedMT, MX>::AtomicIncrement(*pCount_);
+ return val;
+ }
+
+ bool Release(const P&)
+ {
+ bool isZero = false;
+ ThreadingModel< RefCountedMT, MX >::AtomicDecrement( *pCount_, 0, isZero );
+ if ( isZero )
+ {
+ SmallObject<LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>::operator delete(
+ const_cast<CountType *>(pCount_),
+ sizeof(*pCount_));
+ return true;
+ }
+ return false;
+ }
+
+ void Swap(RefCountedMT& rhs)
+ { std::swap(pCount_, rhs.pCount_); }
+
+ enum { destructiveCopy = false };
+
+ private:
+ // Data
+ CountPtrType pCount_;
+ };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class COMRefCounted
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Adapts COM intrusive reference counting to OwnershipPolicy-specific syntax
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ class COMRefCounted
+ {
+ public:
+ COMRefCounted()
+ {}
+
+ template <class U>
+ COMRefCounted(const COMRefCounted<U>&)
+ {}
+
+ static P Clone(const P& val)
+ {
+ if(val!=0)
+ val->AddRef();
+ return val;
+ }
+
+ static bool Release(const P& val)
+ {
+ if(val!=0)
+ val->Release();
+ return false;
+ }
+
+ enum { destructiveCopy = false };
+
+ static void Swap(COMRefCounted&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct DeepCopy
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements deep copy semantics, assumes existence of a Clone() member
+/// function of the pointee type
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct DeepCopy
+ {
+ DeepCopy()
+ {}
+
+ template <class P1>
+ DeepCopy(const DeepCopy<P1>&)
+ {}
+
+ static P Clone(const P& val)
+ { return val->Clone(); }
+
+ static bool Release(const P&)
+ { return true; }
+
+ static void Swap(DeepCopy&)
+ {}
+
+ enum { destructiveCopy = false };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class RefLinked
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements reference linking
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ class LOKI_EXPORT RefLinkedBase
+ {
+ public:
+ RefLinkedBase()
+ { prev_ = next_ = this; }
+
+ RefLinkedBase(const RefLinkedBase& rhs);
+
+ bool Release();
+
+ void Swap(RefLinkedBase& rhs);
+
+ bool Merge( RefLinkedBase & rhs );
+
+ enum { destructiveCopy = false };
+
+ private:
+ static unsigned int CountPrevCycle( const RefLinkedBase * pThis );
+ static unsigned int CountNextCycle( const RefLinkedBase * pThis );
+ bool HasPrevNode( const RefLinkedBase * p ) const;
+ bool HasNextNode( const RefLinkedBase * p ) const;
+
+ mutable const RefLinkedBase* prev_;
+ mutable const RefLinkedBase* next_;
+ };
+ }
+
+ template <class P>
+ class RefLinked : public Private::RefLinkedBase
+ {
+ public:
+ RefLinked()
+ {}
+
+ template <class P1>
+ RefLinked(const RefLinked<P1>& rhs)
+ : Private::RefLinkedBase(rhs)
+ {}
+
+ static P Clone(const P& val)
+ { return val; }
+
+ bool Release(const P&)
+ { return Private::RefLinkedBase::Release(); }
+
+ template < class P1 >
+ bool Merge( RefLinked< P1 > & rhs )
+ {
+ return Private::RefLinkedBase::Merge( rhs );
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class DestructiveCopy
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements destructive copy semantics (a la std::auto_ptr)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ class DestructiveCopy
+ {
+ public:
+ DestructiveCopy()
+ {}
+
+ template <class P1>
+ DestructiveCopy(const DestructiveCopy<P1>&)
+ {}
+
+ template <class P1>
+ static P Clone(P1& val)
+ {
+ P result(val);
+ val = P1();
+ return result;
+ }
+
+ static bool Release(const P&)
+ { return true; }
+
+ static void Swap(DestructiveCopy&)
+ {}
+
+ enum { destructiveCopy = true };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class NoCopy
+///
+/// \ingroup SmartPointerOwnershipGroup
+/// Implementation of the OwnershipPolicy used by SmartPtr
+/// Implements a policy that doesn't allow copying objects
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ class NoCopy
+ {
+ public:
+ NoCopy()
+ {}
+
+ template <class P1>
+ NoCopy(const NoCopy<P1>&)
+ {}
+
+ static P Clone(const P&)
+ {
+ // Make it depended on template parameter
+ static const bool DependedFalse = sizeof(P*) == 0;
+
+ LOKI_STATIC_CHECK(DependedFalse, This_Policy_Disallows_Value_Copying);
+ }
+
+ static bool Release(const P&)
+ { return true; }
+
+ static void Swap(NoCopy&)
+ {}
+
+ enum { destructiveCopy = false };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct AllowConversion
+///
+/// \ingroup SmartPointerConversionGroup
+/// Implementation of the ConversionPolicy used by SmartPtr
+/// Allows implicit conversion from SmartPtr to the pointee type
+////////////////////////////////////////////////////////////////////////////////
+
+ struct AllowConversion
+ {
+ enum { allow = true };
+
+ void Swap(AllowConversion&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct DisallowConversion
+///
+/// \ingroup SmartPointerConversionGroup
+/// Implementation of the ConversionPolicy used by SmartPtr
+/// Does not allow implicit conversion from SmartPtr to the pointee type
+/// You can initialize a DisallowConversion with an AllowConversion
+////////////////////////////////////////////////////////////////////////////////
+
+ struct DisallowConversion
+ {
+ DisallowConversion()
+ {}
+
+ DisallowConversion(const AllowConversion&)
+ {}
+
+ enum { allow = false };
+
+ void Swap(DisallowConversion&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct NoCheck
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Well, it's clear what it does :o)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct NoCheck
+ {
+ NoCheck()
+ {}
+
+ template <class P1>
+ NoCheck(const NoCheck<P1>&)
+ {}
+
+ static void OnDefault(const P&)
+ {}
+
+ static void OnInit(const P&)
+ {}
+
+ static void OnDereference(const P&)
+ {}
+
+ static void Swap(NoCheck&)
+ {}
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct AssertCheck
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer before dereference
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct AssertCheck
+ {
+ AssertCheck()
+ {}
+
+ template <class P1>
+ AssertCheck(const AssertCheck<P1>&)
+ {}
+
+ template <class P1>
+ AssertCheck(const NoCheck<P1>&)
+ {}
+
+ static void OnDefault(const P&)
+ {}
+
+ static void OnInit(const P&)
+ {}
+
+ static void OnDereference(P val)
+ { assert(val); (void)val; }
+
+ static void Swap(AssertCheck&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct AssertCheckStrict
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer against zero upon initialization and before dereference
+/// You can initialize an AssertCheckStrict with an AssertCheck
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct AssertCheckStrict
+ {
+ AssertCheckStrict()
+ {}
+
+ template <class U>
+ AssertCheckStrict(const AssertCheckStrict<U>&)
+ {}
+
+ template <class U>
+ AssertCheckStrict(const AssertCheck<U>&)
+ {}
+
+ template <class P1>
+ AssertCheckStrict(const NoCheck<P1>&)
+ {}
+
+ static void OnDefault(P val)
+ { assert(val); }
+
+ static void OnInit(P val)
+ { assert(val); }
+
+ static void OnDereference(P val)
+ { assert(val); }
+
+ static void Swap(AssertCheckStrict&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct NullPointerException
+///
+/// \ingroup SmartPointerGroup
+/// Used by some implementations of the CheckingPolicy used by SmartPtr
+////////////////////////////////////////////////////////////////////////////////
+
+ struct NullPointerException : public std::runtime_error
+ {
+ NullPointerException() : std::runtime_error(std::string(""))
+ { }
+ const char* what() const throw()
+ { return "Null Pointer Exception"; }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct RejectNullStatic
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer upon initialization and before dereference
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct RejectNullStatic
+ {
+ RejectNullStatic()
+ {}
+
+ template <class P1>
+ RejectNullStatic(const RejectNullStatic<P1>&)
+ {}
+
+ template <class P1>
+ RejectNullStatic(const NoCheck<P1>&)
+ {}
+
+ template <class P1>
+ RejectNullStatic(const AssertCheck<P1>&)
+ {}
+
+ template <class P1>
+ RejectNullStatic(const AssertCheckStrict<P1>&)
+ {}
+
+ static void OnDefault(const P&)
+ {
+ // Make it depended on template parameter
+ static const bool DependedFalse = sizeof(P*) == 0;
+
+ LOKI_STATIC_CHECK(DependedFalse, ERROR_This_Policy_Does_Not_Allow_Default_Initialization);
+ }
+
+ static void OnInit(const P& val)
+ { if (!val) throw NullPointerException(); }
+
+ static void OnDereference(const P& val)
+ { if (!val) throw NullPointerException(); }
+
+ static void Swap(RejectNullStatic&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct RejectNull
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer before dereference
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct RejectNull
+ {
+ RejectNull()
+ {}
+
+ template <class P1>
+ RejectNull(const RejectNull<P1>&)
+ {}
+
+ static void OnInit(P)
+ {}
+
+ static void OnDefault(P)
+ {}
+
+ void OnDereference(P val)
+ { if (!val) throw NullPointerException(); }
+
+ void OnDereference(P val) const
+ { if (!val) throw NullPointerException(); }
+
+ void Swap(RejectNull&)
+ {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \struct RejectNullStrict
+///
+/// \ingroup SmartPointerCheckingGroup
+/// Implementation of the CheckingPolicy used by SmartPtr
+/// Checks the pointer upon initialization and before dereference
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class P>
+ struct RejectNullStrict
+ {
+ RejectNullStrict()
+ {}
+
+ template <class P1>
+ RejectNullStrict(const RejectNullStrict<P1>&)
+ {}
+
+ template <class P1>
+ RejectNullStrict(const RejectNull<P1>&)
+ {}
+
+ static void OnInit(P val)
+ { if (!val) throw NullPointerException(); }
+
+ void OnDereference(P val)
+ { OnInit(val); }
+
+ void OnDereference(P val) const
+ { OnInit(val); }
+
+ void Swap(RejectNullStrict&)
+ {}
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class template SmartPtr (declaration)
+// The reason for all the fuss above
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OwnershipPolicy = RefCounted,
+ class ConversionPolicy = DisallowConversion,
+ template <class> class CheckingPolicy = AssertCheck,
+ template <class> class StoragePolicy = DefaultSPStorage,
+ template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
+ >
+ class SmartPtr;
+
+////////////////////////////////////////////////////////////////////////////////
+// class template SmartPtrDef (definition)
+// this class added to unify the usage of SmartPtr
+// instead of writing SmartPtr<T,OP,CP,KP,SP> write SmartPtrDef<T,OP,CP,KP,SP>::type
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OwnershipPolicy = RefCounted,
+ class ConversionPolicy = DisallowConversion,
+ template <class> class CheckingPolicy = AssertCheck,
+ template <class> class StoragePolicy = DefaultSPStorage,
+ template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
+ >
+ struct SmartPtrDef
+ {
+ typedef SmartPtr
+ <
+ T,
+ OwnershipPolicy,
+ ConversionPolicy,
+ CheckingPolicy,
+ StoragePolicy,
+ ConstnessPolicy
+ >
+ type;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class SmartPtr
+///
+/// \ingroup SmartPointerGroup
+///
+/// \param OwnershipPolicy default = RefCounted,
+/// \param ConversionPolicy default = DisallowConversion,
+/// \param CheckingPolicy default = AssertCheck,
+/// \param StoragePolicy default = DefaultSPStorage
+/// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS
+///
+/// \par IMPORTANT NOTE
+/// Due to threading issues, the OwnershipPolicy has been changed as follows:
+///
+/// - Release() returns a boolean saying if that was the last release
+/// so the pointer can be deleted by the StoragePolicy
+/// - IsUnique() was removed
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OwnershipPolicy,
+ class ConversionPolicy,
+ template <class> class CheckingPolicy,
+ template <class> class StoragePolicy,
+ template <class> class ConstnessPolicy
+ >
+ class SmartPtr
+ : public StoragePolicy<T>
+ , public OwnershipPolicy<typename StoragePolicy<T>::InitPointerType>
+ , public CheckingPolicy<typename StoragePolicy<T>::StoredType>
+ , public ConversionPolicy
+ {
+ typedef StoragePolicy<T> SP;
+ typedef OwnershipPolicy<typename StoragePolicy<T>::InitPointerType> OP;
+ typedef CheckingPolicy<typename StoragePolicy<T>::StoredType> KP;
+ typedef ConversionPolicy CP;
+
+ public:
+ typedef typename ConstnessPolicy<T>::Type* ConstPointerType;
+ typedef typename ConstnessPolicy<T>::Type& ConstReferenceType;
+
+ typedef typename SP::PointerType PointerType;
+ typedef typename SP::StoredType StoredType;
+ typedef typename SP::ReferenceType ReferenceType;
+
+ typedef typename Select<OP::destructiveCopy,SmartPtr, const SmartPtr>::Result
+ CopyArg;
+
+ private:
+ struct NeverMatched {};
+
+#ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
+ typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg;
+ typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg;
+#else
+ typedef const StoredType& ImplicitArg;
+ typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
+#endif
+
+ public:
+
+ SmartPtr()
+ {
+ KP::OnDefault(GetImpl(*this));
+ }
+
+ explicit
+ SmartPtr(ExplicitArg p) : SP(p)
+ {
+ KP::OnInit(GetImpl(*this));
+ }
+
+ SmartPtr(ImplicitArg p) : SP(p)
+ {
+ KP::OnInit(GetImpl(*this));
+ }
+
+ SmartPtr(CopyArg& rhs) : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
+ {
+ GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
+ }
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ SmartPtr(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
+ : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
+ { GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ SmartPtr(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
+ : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
+ {
+ GetImplRef(*this) = OP::Clone(GetImplRef(rhs));
+ }
+
+ SmartPtr(RefToValue<SmartPtr> rhs)
+ : SP(rhs), OP(rhs), KP(rhs), CP(rhs)
+ {}
+
+ operator RefToValue<SmartPtr>()
+ { return RefToValue<SmartPtr>(*this); }
+
+ SmartPtr& operator=(CopyArg& rhs)
+ {
+ SmartPtr temp(rhs);
+ temp.Swap(*this);
+ return *this;
+ }
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ SmartPtr& operator=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
+ {
+ SmartPtr temp(rhs);
+ temp.Swap(*this);
+ return *this;
+ }
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ SmartPtr& operator=(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)
+ {
+ SmartPtr temp(rhs);
+ temp.Swap(*this);
+ return *this;
+ }
+
+ void Swap(SmartPtr& rhs)
+ {
+ OP::Swap(rhs);
+ CP::Swap(rhs);
+ KP::Swap(rhs);
+ SP::Swap(rhs);
+ }
+
+ ~SmartPtr()
+ {
+ if (OP::Release(GetImpl(*static_cast<SP*>(this))))
+ {
+ SP::Destroy();
+ }
+ }
+
+#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
+
+ // old non standard in class definition of friends
+ friend inline void Release(SmartPtr& sp, typename SP::StoredType& p)
+ {
+ p = GetImplRef(sp);
+ GetImplRef(sp) = SP::Default();
+ }
+
+ friend inline void Reset(SmartPtr& sp, typename SP::StoredType p)
+ { SmartPtr(p).Swap(sp); }
+
+#else
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ friend void Release(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
+ typename SP1<T1>::StoredType& p);
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ friend void Reset(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1>& sp,
+ typename SP1<T1>::StoredType p);
+#endif
+
+
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ bool Merge( SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
+ {
+ if ( GetImpl( *this ) != GetImpl( rhs ) )
+ {
+ return false;
+ }
+ return OP::template Merge( rhs );
+ }
+
+ PointerType operator->()
+ {
+ KP::OnDereference(GetImplRef(*this));
+ return SP::operator->();
+ }
+
+ ConstPointerType operator->() const
+ {
+ KP::OnDereference(GetImplRef(*this));
+ return SP::operator->();
+ }
+
+ ReferenceType operator*()
+ {
+ KP::OnDereference(GetImplRef(*this));
+ return SP::operator*();
+ }
+
+ ConstReferenceType operator*() const
+ {
+ KP::OnDereference(GetImplRef(*this));
+ return SP::operator*();
+ }
+
+ bool operator!() const // Enables "if (!sp) ..."
+ { return GetImpl(*this) == 0; }
+
+ static inline T * GetPointer( const SmartPtr & sp )
+ { return GetImpl( sp ); }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ bool operator==(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
+ { return GetImpl(*this) == GetImpl(rhs); }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ bool operator!=(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
+ { return !(*this == rhs); }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ bool operator<(const SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs) const
+ { return GetImpl(*this) < GetImpl(rhs); }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ inline bool operator > ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
+ {
+ return ( GetImpl( rhs ) < GetImpl( *this ) );
+ }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ inline bool operator <= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
+ {
+ return !( GetImpl( rhs ) < GetImpl( *this ) );
+ }
+
+ // Ambiguity buster
+ template
+ <
+ typename T1,
+ template <class> class OP1,
+ class CP1,
+ template <class> class KP1,
+ template <class> class SP1,
+ template <class> class CNP1
+ >
+ inline bool operator >= ( const SmartPtr< T1, OP1, CP1, KP1, SP1, CNP1 > & rhs )
+ {
+ return !( GetImpl( *this ) < GetImpl( rhs ) );
+ }
+
+ private:
+ // Helper for enabling 'if (sp)'
+ struct Tester
+ {
+ Tester(int) {}
+ void dummy() {}
+ };
+
+ typedef void (Tester::*unspecified_boolean_type_)();
+
+ typedef typename Select<CP::allow, Tester, unspecified_boolean_type_>::Result
+ unspecified_boolean_type;
+
+ public:
+ // enable 'if (sp)'
+ operator unspecified_boolean_type() const
+ {
+ return !*this ? 0 : &Tester::dummy;
+ }
+
+ private:
+ // Helper for disallowing automatic conversion
+ struct Insipid
+ {
+ Insipid(PointerType) {}
+ };
+
+ typedef typename Select<CP::allow, PointerType, Insipid>::Result
+ AutomaticConversionResult;
+
+ public:
+ operator AutomaticConversionResult() const
+ { return GetImpl(*this); }
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+// friends
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP
+ >
+ inline void Release(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
+ typename SP<T>::StoredType& p)
+ {
+ p = GetImplRef(sp);
+ GetImplRef(sp) = SP<T>::Default();
+ }
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP
+ >
+ inline void Reset(SmartPtr<T, OP, CP, KP, SP, CNP>& sp,
+ typename SP<T>::StoredType p)
+ { SmartPtr<T, OP, CP, KP, SP, CNP>(p).Swap(sp); }
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// free comparison operators for class template SmartPtr
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator== for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP1,
+ typename U
+ >
+ inline bool operator==(const SmartPtr<T, OP, CP, KP, SP, CNP1 >& lhs,
+ U* rhs)
+ { return GetImpl(lhs) == rhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator== for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP1,
+ typename U
+ >
+ inline bool operator==(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP1 >& rhs)
+ { return rhs == lhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator!= for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator!=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ { return !(lhs == rhs); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator!= for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator!=(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ { return rhs != lhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator< for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator<(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ {
+ return ( GetImpl( lhs ) < rhs );
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator< for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator<(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ {
+ return ( GetImpl( rhs ) < lhs );
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// operator> for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator>(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ { return rhs < lhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator> for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator>(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ { return rhs < lhs; }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator<= for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator<=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ { return !(rhs < lhs); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator<= for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator<=(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ { return !(rhs < lhs); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator>= for lhs = SmartPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator>=(const SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ U* rhs)
+ { return !(lhs < rhs); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// operator>= for lhs = raw pointer, rhs = SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP,
+ typename U
+ >
+ inline bool operator>=(U* lhs,
+ const SmartPtr<T, OP, CP, KP, SP, CNP >& rhs)
+ { return !(lhs < rhs); }
+
+} // namespace Loki
+
+////////////////////////////////////////////////////////////////////////////////
+/// specialization of std::less for SmartPtr
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+namespace std
+{
+ template
+ <
+ typename T,
+ template <class> class OP,
+ class CP,
+ template <class> class KP,
+ template <class> class SP,
+ template <class> class CNP
+ >
+ struct less< Loki::SmartPtr<T, OP, CP, KP, SP, CNP > >
+ : public binary_function<Loki::SmartPtr<T, OP, CP, KP, SP, CNP >,
+ Loki::SmartPtr<T, OP, CP, KP, SP, CNP >, bool>
+ {
+ bool operator()(const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& lhs,
+ const Loki::SmartPtr<T, OP, CP, KP, SP, CNP >& rhs) const
+ { return less<T*>()(GetImpl(lhs), GetImpl(rhs)); }
+ };
+}
+
+#endif // end file guardian
+
diff --git a/shared/loki/StrongPtr.h b/shared/loki/StrongPtr.h
new file mode 100644
index 00000000..7ec9766f
--- /dev/null
+++ b/shared/loki/StrongPtr.h
@@ -0,0 +1,1697 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 Rich Sposato
+// The copyright on this file is protected under the terms of the MIT license.
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_STRONG_PTR_INC_
+#define LOKI_STRONG_PTR_INC_
+
+// $Id: StrongPtr.h 914 2008-12-19 00:39:29Z rich_sposato $
+
+
+#include <loki/SmartPtr.h>
+#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
+ #include <loki/Threads.h>
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \par Terminology
+/// These terms are used within this file's comments.
+/// -# StrongPtr : Class used to implement both strong and weak pointers. The
+/// second template parameter determines if a StrongPtr is weak or strong.
+/// -# Strong pointer : A pointer that claims ownership of a shared object.
+/// When the last strong copointer dies, the object is destroyed even if
+/// there are weak copointers.
+/// -# Weak pointer : A pointer that does not own the shared object it points
+/// to. It only destroys the shared object if there no strong copointers
+/// exist when it dies.
+/// -# Copointers : All the pointers that refer to the same shared object.
+/// The copointers must have the same ownership policy, but the other
+/// policies may be different.
+/// -# Pointee : The shared object.
+///
+/// \par OwnershipPolicy
+/// The ownership policy has the pointer to the actual object, and it also
+/// keeps track of the strong and weak copointers so that it can know if any
+/// strong copointers remain. The plain pointer it maintains is stored as a
+/// void pointer, which allows the ownership policy classes to be monolithic
+/// classes instead of template classes. As monolithic classes, they reduce
+/// amount of code-bloat.
+///
+/// \par Writing Your Own OwnershipPolicy
+/// If you write your own policy, you must implement these 12 functions:
+/// -# explicit YourPolicy( bool strong )
+/// -# YourPolicy( void * p, bool strong )
+/// -# YourPolicy( const YourPolicy & rhs, bool strong )
+/// -# bool Release( bool strong )
+/// -# void Increment( bool strong )
+/// -# bool Decrement( bool strong )
+/// -# bool HasStrongPointer( void ) const
+/// -# void Swap( YourPolicy & rhs )
+/// -# void SetPointer( void * p )
+/// -# void ZapPointer( void )
+/// -# void * GetPointer( void ) const
+/// -# void * & GetPointerRef( void ) const
+/// It is strongly recommended that all 12 of these functions be protected
+/// instead of public. These two functions are optional for single-threaded
+/// policies, but required for multi-threaded policies:
+/// -# void Lock( void ) const
+/// -# void Unlock( void ) const
+/// This function is entirely optional:
+/// -# bool Merge( TwoRefLinks & rhs )
+///
+/// \par DeletePolicy
+/// The delete policy provides a mechanism to destroy an object and a default
+/// value for an uninitialized pointer. You can override this policy with
+/// your own when using the Singleton, NullObject, or Prototype design
+/// patterns.
+///
+/// \par Writing Your Own DeletePolicy
+/// If you write your own policy, you must implement these 3 functions:
+/// -# void static Delete( const P * p )
+/// -# static P * Default( void )
+/// -# void Swap( YourResetPolicy & )
+///
+/// \par ResetPolicy
+/// A reset policy tells the ReleaseAll and ResetAll functions whether they
+/// should release or reset the StrongPtr copointers. These functions do
+/// not affect just one StrongPtr, but all copointers. That is unlike
+/// SmartPtr where the Release and Reset functions only affect 1 SmartPtr,
+/// and leave all copointers untouched. A useful trick you can do with the
+/// ResetPolicy is to not allow reset when a strong pointer exists, and then
+/// use the NoCheck policy for all strong pointers. The reset policy
+/// guarantees the strong pointers always have a valid pointee, so checking
+/// is not required; but weak pointers may still require checking.
+///
+/// \par Writing Your Own ResetPolicy
+/// If you write your own policy, you must implement these 2 functions:
+/// -# bool OnReleaseAll( bool ) const
+/// -# bool OnResetAll( bool ) const
+/// The bool parameter means that this was called with a strong pointer or
+/// one of its copointers is strong. The return value means the pointer
+/// can be reset or released.
+///
+/// \defgroup StrongPointerOwnershipGroup StrongPtr Ownership policies
+/// \ingroup SmartPointerGroup
+/// \defgroup StrongPointerDeleteGroup Delete policies
+/// \ingroup SmartPointerGroup
+/// \defgroup StrongPointerResetGroup Reset policies
+/// \ingroup SmartPointerGroup
+////////////////////////////////////////////////////////////////////////////////
+
+
+namespace Loki
+{
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class DeleteUsingFree
+///
+/// \ingroup StrongPointerDeleteGroup
+/// Implementation of the DeletePolicy used by StrongPtr. Uses explicit call
+/// to T's destructor followed by call to free. This policy is useful for
+/// managing the lifetime of pointers to structs returned by C functions.
+////////////////////////////////////////////////////////////////////////////////
+
+template < class P >
+class DeleteUsingFree
+{
+public:
+ inline void static Delete( const P * p )
+ {
+ if ( 0 != p )
+ {
+ p->~P();
+ ::free( p );
+ }
+ }
+
+ /// Provides default value to initialize the pointer
+ inline static P * Default( void )
+ {
+ return 0;
+ }
+
+ inline void Swap( DeleteUsingFree & ) {}
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class DeleteNothing
+///
+/// \ingroup StrongPointerDeleteGroup
+/// Implementation of the DeletePolicy used by StrongPtr. This will never
+/// delete anything. You can use this policy with pointers to an undefined
+/// type or a pure interface class with a protected destructor.
+////////////////////////////////////////////////////////////////////////////////
+
+template < class P >
+class DeleteNothing
+{
+public:
+ inline static void Delete( const P * )
+ {
+ // Do nothing at all!
+ }
+
+ inline static P * Default( void )
+ {
+ return 0;
+ }
+
+ inline void Swap( DeleteNothing & ) {}
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class DeleteSingle
+///
+/// \ingroup StrongPointerDeleteGroup
+/// Implementation of the DeletePolicy used by StrongPtr. This deletes just
+/// one shared object. This is the default class for the DeletePolicy.
+////////////////////////////////////////////////////////////////////////////////
+
+template < class P >
+class DeleteSingle
+{
+public:
+ inline static void Delete( const P * p )
+ {
+ /** @note If you see an error message about a negative subscript, that
+ means your are attempting to use Loki to delete an incomplete type.
+ Please don't use this policy with incomplete types; you may want to
+ use DeleteNothing instead.
+ */
+ typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
+ delete p;
+ }
+
+ inline static P * Default( void )
+ {
+ return 0;
+ }
+
+ inline void Swap( DeleteSingle & ) {}
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class DeleteArray
+///
+/// \ingroup StrongPointerDeleteGroup
+/// Implementation of the DeletePolicy used by StrongPtr. This deletes an
+/// array of shared objects.
+////////////////////////////////////////////////////////////////////////////////
+
+template < class P >
+class DeleteArray
+{
+public:
+ inline static void Delete( const P * p )
+ {
+ /** @note If you see an error message about a negative subscript, that
+ means your are attempting to use Loki to delete an incomplete type.
+ Please don't use this policy with incomplete types; you may want to
+ use DeleteNothing instead.
+ */
+ typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
+ delete [] p;
+ }
+
+ inline static P * Default( void )
+ {
+ return 0;
+ }
+
+ inline void Swap( DeleteArray & ) {}
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class CantResetWithStrong
+///
+/// \ingroup StrongPointerResetGroup
+/// Implementation of the ResetPolicy used by StrongPtr. This is the default
+/// ResetPolicy for StrongPtr. It forbids reset and release only if a strong
+/// copointer exists.
+////////////////////////////////////////////////////////////////////////////////
+
+template < class P >
+struct CantResetWithStrong
+{
+ inline bool OnReleaseAll( bool hasStrongPtr ) const
+ {
+ return ! hasStrongPtr;
+ }
+
+ inline bool OnResetAll( bool hasStrongPtr ) const
+ {
+ return ! hasStrongPtr;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class AllowReset
+///
+/// \ingroup StrongPointerResetGroup
+/// Implementation of the ResetPolicy used by StrongPtr. It allows reset and
+/// release under any circumstance.
+////////////////////////////////////////////////////////////////////////////////
+
+template < class P >
+struct AllowReset
+{
+ inline bool OnReleaseAll( bool ) const
+ {
+ return true;
+ }
+ inline bool OnResetAll( bool ) const
+ {
+ return true;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class NeverReset
+///
+/// \ingroup StrongPointerResetGroup
+/// Implementation of the ResetPolicy used by StrongPtr. It forbids reset and
+/// release under any circumstance.
+////////////////////////////////////////////////////////////////////////////////
+
+template < class P >
+struct NeverReset
+{
+ inline bool OnReleaseAll( bool ) const
+ {
+ return false;
+ }
+ inline bool OnResetAll( bool ) const
+ {
+ return false;
+ }
+};
+
+// ----------------------------------------------------------------------------
+
+namespace Private
+{
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class TwoRefCountInfo
+///
+/// \ingroup StrongPointerOwnershipGroup
+/// Implementation detail for reference counting strong and weak pointers.
+/// It maintains a void pointer and 2 reference counts. Since it is just a
+/// class for managing implementation details, it is not intended to be used
+/// directly - which is why it is in a private namespace. Each instance is a
+/// shared resource for all copointers, and there should be only one of these
+/// for each set of copointers. This class is small, trivial, and inline.
+////////////////////////////////////////////////////////////////////////////////
+
+class LOKI_EXPORT TwoRefCountInfo
+{
+public:
+
+ inline explicit TwoRefCountInfo( bool strong )
+ : m_pointer( 0 )
+ , m_strongCount( strong ? 1 : 0 )
+ , m_weakCount( strong ? 0 : 1 )
+ {
+ }
+
+ inline TwoRefCountInfo( void * p, bool strong )
+ : m_pointer( p )
+ , m_strongCount( strong ? 1 : 0 )
+ , m_weakCount( strong ? 0 : 1 )
+ {
+ }
+
+ inline ~TwoRefCountInfo( void )
+ {
+ assert( 0 == m_strongCount );
+ assert( 0 == m_weakCount );
+ }
+
+ inline bool HasStrongPointer( void ) const
+ {
+ return ( 0 < m_strongCount );
+ }
+
+ inline bool HasWeakPointer( void ) const
+ {
+ return ( 0 < m_weakCount );
+ }
+
+ inline void IncStrongCount( void )
+ {
+ ++m_strongCount;
+ }
+
+ inline void IncWeakCount( void )
+ {
+ ++m_weakCount;
+ }
+
+ inline bool DecStrongCount( void )
+ {
+ assert( 0 < m_strongCount );
+ --m_strongCount;
+ const bool isZero = ( 0 == m_strongCount );
+ return isZero;
+ }
+
+ inline void DecWeakCount( void )
+ {
+ assert( 0 < m_weakCount );
+ --m_weakCount;
+ }
+
+ inline void ZapPointer( void )
+ {
+ m_pointer = 0;
+ }
+
+ void SetPointer( void * p )
+ {
+ m_pointer = p;
+ }
+
+ inline void * GetPointer( void ) const
+ {
+ return m_pointer;
+ }
+
+ inline void * & GetPointerRef( void ) const
+ {
+ return const_cast< void * & >( m_pointer );
+ }
+
+private:
+ /// Copy-constructor not implemented.
+ TwoRefCountInfo( const TwoRefCountInfo & );
+ /// Copy-assignment operator not implemented.
+ TwoRefCountInfo & operator = ( const TwoRefCountInfo & );
+
+ void * m_pointer;
+ unsigned int m_strongCount;
+ unsigned int m_weakCount;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class LockableTwoRefCountInfo
+///
+/// \ingroup StrongPointerOwnershipGroup
+/// Implementation detail for thread-safe reference counting for strong and
+/// weak pointers. It uses TwoRefCountInfo to manage the pointer and counts.
+/// All this does is provide a thread safety mechanism. Since it is just a
+/// class for managing implementation details, it is not intended to be used
+/// directly - which is why it is in a private namespace. Each instance is a
+/// shared resource for all copointers, and there should be only one of these
+/// for each set of copointers. This class is small, trivial, and inline.
+///
+/// \note This class is not designed for use with a single-threaded model.
+/// Tests using a single-threaded model will not run properly, but tests in a
+/// multi-threaded model with either class-level-locking or object-level-locking
+/// do run properly.
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
+
+class LOKI_EXPORT LockableTwoRefCountInfo
+ : private Loki::Private::TwoRefCountInfo
+{
+public:
+
+ inline explicit LockableTwoRefCountInfo( bool strong )
+ : TwoRefCountInfo( strong )
+ , m_Mutex()
+ {
+ }
+
+ LockableTwoRefCountInfo( void * p, bool strong )
+ : TwoRefCountInfo( p, strong )
+ , m_Mutex()
+ {
+ }
+
+ inline ~LockableTwoRefCountInfo( void )
+ {
+ }
+
+ inline void Lock( void ) const
+ {
+ m_Mutex.Lock();
+ }
+
+ inline void Unlock( void ) const
+ {
+ m_Mutex.Unlock();
+ }
+
+ inline bool HasStrongPointer( void ) const
+ {
+ m_Mutex.Lock();
+ const bool has = TwoRefCountInfo::HasStrongPointer();
+ m_Mutex.Unlock();
+ return has;
+ }
+
+ inline bool HasWeakPointer( void ) const
+ {
+ m_Mutex.Lock();
+ const bool has = TwoRefCountInfo::HasWeakPointer();
+ m_Mutex.Unlock();
+ return has;
+ }
+
+ inline void IncStrongCount( void )
+ {
+ m_Mutex.Lock();
+ TwoRefCountInfo::IncStrongCount();
+ m_Mutex.Unlock();
+ }
+
+ inline void IncWeakCount( void )
+ {
+ m_Mutex.Lock();
+ TwoRefCountInfo::IncWeakCount();
+ m_Mutex.Unlock();
+ }
+
+ inline bool DecStrongCount( void )
+ {
+ m_Mutex.Lock();
+ const bool isZero = TwoRefCountInfo::DecStrongCount();
+ m_Mutex.Unlock();
+ return isZero;
+ }
+
+ inline void DecWeakCount( void )
+ {
+ m_Mutex.Lock();
+ TwoRefCountInfo::DecWeakCount();
+ m_Mutex.Unlock();
+ }
+
+ inline void ZapPointer( void )
+ {
+ m_Mutex.Lock();
+ TwoRefCountInfo::ZapPointer();
+ m_Mutex.Unlock();
+ }
+
+ void SetPointer( void * p )
+ {
+ m_Mutex.Lock();
+ TwoRefCountInfo::SetPointer( p );
+ m_Mutex.Unlock();
+ }
+
+ inline void * GetPointer( void ) const
+ {
+ return TwoRefCountInfo::GetPointer();
+ }
+
+ inline void * & GetPointerRef( void ) const
+ {
+ return TwoRefCountInfo::GetPointerRef();
+ }
+
+private:
+ /// Default constructor is not available.
+ LockableTwoRefCountInfo( void );
+ /// Copy constructor is not available.
+ LockableTwoRefCountInfo( const LockableTwoRefCountInfo & );
+ /// Copy-assignment operator is not available.
+ LockableTwoRefCountInfo & operator = ( const LockableTwoRefCountInfo & );
+
+ mutable LOKI_DEFAULT_MUTEX m_Mutex;
+};
+
+#endif // if object-level-locking or class-level-locking
+
+} // end namespace Private
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class TwoRefCounts
+///
+/// \ingroup StrongPointerOwnershipGroup
+/// This implementation of StrongPtr's OwnershipPolicy uses a pointer to a
+/// shared instance of TwoRefCountInfo. This is the default policy for
+/// OwnershipPolicy. Some functions are trivial enough to be inline, while
+/// others are implemented elsewhere. It is not thread safe, and is intended
+/// for single-threaded environments.
+////////////////////////////////////////////////////////////////////////////////
+
+class LOKI_EXPORT TwoRefCounts
+{
+protected:
+
+ explicit TwoRefCounts( bool strong );
+
+ TwoRefCounts( const void * p, bool strong );
+
+ TwoRefCounts( const TwoRefCounts & rhs, bool strong ) :
+ m_counts( rhs.m_counts )
+ {
+ Increment( strong );
+ }
+
+ /** The destructor does not need to do anything since the call to
+ ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
+ this dtor would have done.
+ */
+ inline ~TwoRefCounts( void ) {}
+
+ inline bool Release( bool strong )
+ {
+ return Decrement( strong );
+ }
+
+ bool HasStrongPointer( void ) const
+ {
+ return m_counts->HasStrongPointer();
+ }
+
+ void Swap( TwoRefCounts & rhs );
+
+ void SetPointer( void * p )
+ {
+ m_counts->SetPointer( p );
+ }
+
+ void ZapPointer( void );
+
+ inline void * & GetPointerRef( void ) const
+ {
+ return m_counts->GetPointerRef();
+ }
+
+ inline void * GetPointer( void ) const
+ {
+ return m_counts->GetPointer();
+ }
+
+private:
+ TwoRefCounts( void );
+ TwoRefCounts & operator = ( const TwoRefCounts & );
+
+ void Increment( bool strong );
+
+ bool Decrement( bool strong );
+
+ /// Pointer to all shared data.
+ Loki::Private::TwoRefCountInfo * m_counts;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class LockableTwoRefCounts
+///
+/// \ingroup StrongPointerOwnershipGroup
+/// This implementation of StrongPtr's OwnershipPolicy uses a pointer to a
+/// shared instance of LockableTwoRefCountInfo. It behaves very similarly to
+/// TwoRefCounts, except that it provides thread-safety. Some functions are
+/// trivial enough to be inline, while others are implemented elsewhere.
+///
+/// \note This class is not designed for use with a single-threaded model.
+/// Tests using a single-threaded model will not run properly, but tests in a
+/// multi-threaded model with either class-level-locking or object-level-locking
+/// do run properly.
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
+
+class LOKI_EXPORT LockableTwoRefCounts
+{
+ typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator;
+
+protected:
+
+ explicit LockableTwoRefCounts( bool strong )
+ : m_counts( NULL )
+ {
+ void * temp = ThreadSafePointerAllocator::operator new(
+ sizeof(Loki::Private::LockableTwoRefCountInfo) );
+#ifdef DO_EXTRA_LOKI_TESTS
+ assert( temp != 0 );
+#endif
+ m_counts = new ( temp ) Loki::Private::LockableTwoRefCountInfo( strong );
+ }
+
+ LockableTwoRefCounts( const void * p, bool strong )
+ : m_counts( NULL )
+ {
+ void * temp = ThreadSafePointerAllocator::operator new(
+ sizeof(Loki::Private::LockableTwoRefCountInfo) );
+#ifdef DO_EXTRA_LOKI_TESTS
+ assert( temp != 0 );
+#endif
+ void * p2 = const_cast< void * >( p );
+ m_counts = new ( temp )
+ Loki::Private::LockableTwoRefCountInfo( p2, strong );
+ }
+
+ LockableTwoRefCounts( const LockableTwoRefCounts & rhs, bool strong ) :
+ m_counts( rhs.m_counts )
+ {
+ Increment( strong );
+ }
+
+ /** The destructor does not need to do anything since the call to
+ ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
+ this dtor would have done.
+ */
+ inline ~LockableTwoRefCounts( void ) {}
+
+ inline void Lock( void ) const
+ {
+ m_counts->Lock();
+ }
+
+ inline void Unlock( void ) const
+ {
+ m_counts->Unlock();
+ }
+
+ inline bool Release( bool strong )
+ {
+ return Decrement( strong );
+ }
+
+ void Increment( bool strong )
+ {
+ if ( strong )
+ {
+ m_counts->IncStrongCount();
+ }
+ else
+ {
+ m_counts->IncWeakCount();
+ }
+ }
+
+ bool Decrement( bool strong )
+ {
+ bool noStrongPointers = false;
+ if ( strong )
+ {
+ noStrongPointers = m_counts->DecStrongCount();
+ }
+ else
+ {
+ m_counts->DecWeakCount();
+ noStrongPointers = !m_counts->HasStrongPointer();
+ }
+ return noStrongPointers;
+ }
+
+ bool HasStrongPointer( void ) const
+ {
+ return m_counts->HasStrongPointer();
+ }
+
+ void Swap( LockableTwoRefCounts & rhs )
+ {
+ std::swap( m_counts, rhs.m_counts );
+ }
+
+ void SetPointer( void * p )
+ {
+ m_counts->SetPointer( p );
+ }
+
+ void ZapPointer( void )
+ {
+#ifdef DO_EXTRA_LOKI_TESTS
+ assert( !m_counts->HasStrongPointer() );
+#endif
+ if ( m_counts->HasWeakPointer() )
+ {
+ m_counts->ZapPointer();
+ }
+ else
+ {
+ ThreadSafePointerAllocator::operator delete ( m_counts,
+ sizeof(Loki::Private::LockableTwoRefCountInfo) );
+ m_counts = NULL;
+ }
+ }
+
+ inline void * GetPointer( void ) const
+ {
+ return m_counts->GetPointer();
+ }
+
+ inline void * & GetPointerRef( void ) const
+ {
+ return m_counts->GetPointerRef();
+ }
+
+private:
+ LockableTwoRefCounts( void );
+ LockableTwoRefCounts & operator = ( const LockableTwoRefCounts & );
+
+ /// Pointer to all shared data.
+ Loki::Private::LockableTwoRefCountInfo * m_counts;
+};
+
+#endif // if object-level-locking or class-level-locking
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class TwoRefLinks
+///
+/// \ingroup StrongPointerOwnershipGroup
+/// This implementation of StrongPtr's OwnershipPolicy uses a doubly-linked
+/// cycle of copointers to a shared object. Some functions are trivial enough
+/// to be inline, while others are implemented in elsewhere. It is not thread
+/// safe, and is intended for single-threaded environments.
+////////////////////////////////////////////////////////////////////////////////
+
+class LOKI_EXPORT TwoRefLinks
+{
+protected:
+
+ inline explicit TwoRefLinks( bool strong )
+ : m_pointer( 0 )
+ , m_strong( strong )
+ {
+ m_prev = m_next = this;
+ }
+
+ TwoRefLinks( const void * p, bool strong );
+
+ TwoRefLinks( const TwoRefLinks & rhs, bool strong );
+
+ bool Release( bool strong );
+
+ void Swap( TwoRefLinks & rhs );
+
+ bool Merge( TwoRefLinks & rhs );
+
+ bool HasStrongPointer( void ) const;
+
+ inline void ZapPointer( void )
+ {
+ ZapAllNodes();
+ }
+
+ void SetPointer( void * p );
+
+ inline void * GetPointer( void ) const
+ {
+ return m_pointer;
+ }
+
+ inline void * & GetPointerRef( void ) const
+ {
+ return const_cast< void * & >( m_pointer );
+ }
+
+private:
+ static unsigned int CountPrevCycle( const TwoRefLinks * pThis );
+ static unsigned int CountNextCycle( const TwoRefLinks * pThis );
+
+ /// Not implemented.
+ TwoRefLinks( void );
+ /// Not implemented.
+ TwoRefLinks & operator = ( const TwoRefLinks & );
+
+ bool HasPrevNode( const TwoRefLinks * p ) const;
+ bool HasNextNode( const TwoRefLinks * p ) const;
+ bool AllNodesHaveSamePointer( void ) const;
+ void ZapAllNodes( void );
+
+ void * m_pointer;
+ mutable TwoRefLinks * m_prev;
+ mutable TwoRefLinks * m_next;
+ const bool m_strong;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class StrongPtr
+///
+/// \ingroup SmartPointerGroup
+///
+/// \param Strong default = true,
+/// \param OwnershipPolicy default = TwoRefCounts,
+/// \param ConversionPolicy default = DisallowConversion,
+/// \param CheckingPolicy default = AssertCheck,
+/// \param ResetPolicy default = CantResetWithStrong,
+/// \param DeletePolicy default = DeleteSingle
+/// \param ConstnessPolicy default = LOKI_DEFAULT_CONSTNESS
+////////////////////////////////////////////////////////////////////////////////
+
+template
+<
+ typename T,
+ bool Strong = true,
+ class OwnershipPolicy = Loki::TwoRefCounts,
+ class ConversionPolicy = Loki::DisallowConversion,
+ template < class > class CheckingPolicy = Loki::AssertCheck,
+ template < class > class ResetPolicy = Loki::CantResetWithStrong,
+ template < class > class DeletePolicy = Loki::DeleteSingle,
+ template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
+>
+class StrongPtr
+ : public OwnershipPolicy
+ , public ConversionPolicy
+ , public CheckingPolicy< T * >
+ , public ResetPolicy< T >
+ , public DeletePolicy< T >
+{
+ typedef ConversionPolicy CP;
+ typedef CheckingPolicy< T * > KP;
+ typedef ResetPolicy< T > RP;
+ typedef DeletePolicy< T > DP;
+
+public:
+
+ typedef OwnershipPolicy OP;
+
+ typedef T * StoredType; // the type of the pointer
+ typedef T * PointerType; // type returned by operator->
+ typedef T & ReferenceType; // type returned by operator*
+
+ typedef typename ConstnessPolicy< T >::Type * ConstPointerType;
+ typedef typename ConstnessPolicy< T >::Type & ConstReferenceType;
+
+private:
+ struct NeverMatched {};
+
+#ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
+ typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg;
+ typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg;
+#else
+ typedef const StoredType& ImplicitArg;
+ typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
+#endif
+
+public:
+
+ StrongPtr( void ) : OP( Strong )
+ {
+ KP::OnDefault( GetPointer() );
+ }
+
+ explicit StrongPtr( ExplicitArg p ) : OP( p, Strong )
+ {
+ KP::OnInit( GetPointer() );
+ }
+
+ StrongPtr( ImplicitArg p ) : OP( p, Strong )
+ {
+ KP::OnInit( GetPointer() );
+ }
+
+ StrongPtr( const StrongPtr & rhs )
+ : OP( rhs, Strong ), CP( rhs ), KP( rhs ), DP( rhs )
+ {
+ }
+
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ StrongPtr(
+ const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
+ : OP( rhs, Strong )
+ {
+ }
+
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ StrongPtr(
+ StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
+ : OP( rhs, Strong )
+ {
+ }
+
+ StrongPtr( RefToValue< StrongPtr > rhs )
+ : OP( rhs, Strong ), KP( rhs ), CP( rhs ), DP( rhs )
+ {
+ }
+
+ operator RefToValue< StrongPtr >( void )
+ {
+ return RefToValue< StrongPtr >( *this );
+ }
+
+ StrongPtr & operator = ( const StrongPtr & rhs )
+ {
+ if ( GetPointer() != rhs.GetPointer() )
+ {
+ StrongPtr temp( rhs );
+ temp.Swap( *this );
+ }
+ return *this;
+ }
+
+ StrongPtr & operator = ( T * p )
+ {
+ if ( GetPointer() != p )
+ {
+ StrongPtr temp( p );
+ Swap( temp );
+ }
+ return *this;
+ }
+
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ StrongPtr & operator = (
+ const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
+ {
+ if ( !rhs.Equals( GetPointer() ) )
+ {
+ StrongPtr temp( rhs );
+ temp.Swap( *this );
+ }
+ return *this;
+ }
+
+ bool IsStrong( void ) const
+ {
+ return Strong;
+ }
+
+ void Swap( StrongPtr & rhs )
+ {
+ OP::Swap( rhs );
+ CP::Swap( rhs );
+ KP::Swap( rhs );
+ DP::Swap( rhs );
+ }
+
+ ~StrongPtr()
+ {
+ if ( OP::Release( Strong ) )
+ {
+ // Must zap the pointer before deleteing the object. Otherwise a
+ // cycle of weak pointers will lead to recursion, which leads to
+ // to deleting the shared object multiple times, which leads to
+ // undefined behavior. Therefore, this must get pointer before
+ // zapping it, and then delete the temp pointer.
+ T * p = GetPointer();
+ OP::ZapPointer();
+ if ( p != 0 )
+ {
+ DP::Delete( p );
+ }
+ }
+ }
+
+#ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
+
+ // old non standard in class definition of friends
+ friend bool ReleaseAll( StrongPtr & sp,
+ typename StrongPtr::StoredType & p )
+ {
+ if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
+ {
+ return false;
+ }
+ p = sp.GetPointer();
+ sp.OP::SetPointer( sp.DP::Default() );
+ return true;
+ }
+
+ friend bool ResetAll( StrongPtr & sp,
+ typename StrongPtr::StoredType p )
+ {
+ if ( sp.OP::GetPointer() == p )
+ {
+ return true;
+ }
+ if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
+ {
+ return false;
+ }
+ sp.DP::Delete( sp.GetPointer() );
+ sp.OP::SetPointer( p );
+ return true;
+ }
+
+#else
+
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ friend bool ReleaseAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
+ typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType & p );
+
+
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ friend bool ResetAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
+ typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType p );
+
+#endif
+
+
+ /** Merges ownership of two StrongPtr's that point to same shared object
+ but are not copointers. Requires Merge function in OwnershipPolicy.
+ \return True for success, false if not pointer to same object.
+ */
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ bool Merge( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
+ {
+ if ( OP::GetPointer() != rhs.OP::GetPointer() )
+ {
+ return false;
+ }
+ return OP::Merge( rhs );
+ }
+
+ /** Locks StrongPtr so other threads can't affect pointer. Requires the
+ OwnershipPolicy to have Lock function.
+ */
+ void Lock( void )
+ {
+ OP::Lock();
+ }
+
+ /** Unlocks StrongPtr so other threads can affect pointer. Requires the
+ OwnershipPolicy to have Unlock function.
+ */
+ void Unlock( void )
+ {
+ OP::Unlock();
+ }
+
+ PointerType operator -> ()
+ {
+ KP::OnDereference( GetPointer() );
+ return GetPointer();
+ }
+
+ ConstPointerType operator -> () const
+ {
+ KP::OnDereference( GetPointer() );
+ return GetPointer();
+ }
+
+ ReferenceType operator * ()
+ {
+ KP::OnDereference( GetPointer() );
+ return * GetPointer();
+ }
+
+ ConstReferenceType operator * () const
+ {
+ KP::OnDereference( GetPointer() );
+ return * GetPointer();
+ }
+
+ /// Helper function which can be called to avoid exposing GetPointer function.
+ template < class T1 >
+ bool Equals( const T1 * p ) const
+ {
+ return ( GetPointer() == p );
+ }
+
+ /// Helper function which can be called to avoid exposing GetPointer function.
+ template < class T1 >
+ bool LessThan( const T1 * p ) const
+ {
+ return ( GetPointer() < p );
+ }
+
+ /// Helper function which can be called to avoid exposing GetPointer function.
+ template < class T1 >
+ bool GreaterThan( const T1 * p ) const
+ {
+ return ( GetPointer() > p );
+ }
+
+ /// Equality comparison operator is templated to handle ambiguity.
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ bool operator == (
+ const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
+ {
+ return ( rhs.Equals( GetPointer() ) );
+ }
+
+ /// Inequality comparison operator is templated to handle ambiguity.
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ bool operator != (
+ const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
+ {
+ return !( rhs.Equals( GetPointer() ) );
+ }
+
+ /// Less-than comparison operator is templated to handle ambiguity.
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ bool operator < (
+ const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
+ {
+ return ( rhs.GreaterThan( GetPointer() ) );
+ }
+
+ /// Greater-than comparison operator is templated to handle ambiguity.
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ inline bool operator > (
+ const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
+ {
+ return ( rhs.LessThan( GetPointer() ) );
+ }
+
+ /// Less-than-or-equal-to operator is templated to handle ambiguity.
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ inline bool operator <= (
+ const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
+ {
+ return !( rhs.LessThan( GetPointer() ) );
+ }
+
+ /// Greater-than-or-equal-to operator is templated to handle ambiguity.
+ template
+ <
+ typename T1,
+ bool S1,
+ class OP1,
+ class CP1,
+ template < class > class KP1,
+ template < class > class RP1,
+ template < class > class DP1,
+ template < class > class CNP1
+ >
+ inline bool operator >= (
+ const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
+ {
+ return !( rhs.GreaterThan( GetPointer() ) );
+ }
+
+ inline bool operator ! () const // Enables "if ( !sp ) ..."
+ {
+ return ( 0 == OP::GetPointer() );
+ }
+
+protected:
+
+ inline PointerType GetPointer( void )
+ {
+ return reinterpret_cast< PointerType >( OP::GetPointer() );
+ }
+
+ inline ConstPointerType GetPointer( void ) const
+ {
+ return reinterpret_cast< ConstPointerType >( OP::GetPointer() );
+ }
+
+private:
+
+ inline ReferenceType GetPointerRef( void )
+ {
+ return reinterpret_cast< ReferenceType >( OP::GetPointerRef() );
+ }
+
+ inline ConstReferenceType GetPointerRef( void ) const
+ {
+ return reinterpret_cast< ConstReferenceType >( OP::GetPointerRef() );
+ }
+
+ // Helper for enabling 'if (sp)'
+ struct Tester
+ {
+ Tester(int) {}
+ void dummy() {}
+ };
+
+ typedef void (Tester::*unspecified_boolean_type_)();
+
+ typedef typename Select< CP::allow, Tester, unspecified_boolean_type_ >::Result
+ unspecified_boolean_type;
+
+public:
+ // enable 'if (sp)'
+ operator unspecified_boolean_type() const
+ {
+ return !*this ? 0 : &Tester::dummy;
+ }
+
+private:
+ // Helper for disallowing automatic conversion
+ struct Insipid
+ {
+ Insipid(PointerType) {}
+ };
+
+ typedef typename Select< CP::allow, PointerType, Insipid >::Result
+ AutomaticConversionResult;
+
+public:
+ operator AutomaticConversionResult() const
+ {
+ return GetPointer();
+ }
+
+};
+
+// ----------------------------------------------------------------------------
+
+// friend functions
+
+#ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
+
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
+ typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType & p )
+{
+ if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
+ {
+ return false;
+ }
+ p = sp.GetPointer();
+ sp.OP::SetPointer( sp.DP<T>::Default() );
+ return true;
+}
+
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+bool ResetAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
+ typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType p )
+{
+ if ( sp.OP::GetPointer() == p )
+ {
+ return true;
+ }
+ if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
+ {
+ return false;
+ }
+ sp.DP<T>::Delete( sp.GetPointer() );
+ sp.OP::SetPointer( p );
+ return true;
+}
+#endif
+
+
+// free comparison operators for class template StrongPtr
+
+/// operator== for lhs = StrongPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator == (
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
+{
+ return ( lhs.Equals( rhs ) );
+}
+
+/// operator== for lhs = raw pointer, rhs = StrongPtr
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator == ( U * lhs,
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
+{
+ return ( rhs.Equals( lhs ) );
+}
+
+/// operator!= for lhs = StrongPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator != (
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
+{
+ return !( lhs.Equals( rhs ) );
+}
+
+/// operator!= for lhs = raw pointer, rhs = StrongPtr
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator != ( U * lhs,
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
+{
+ return !( rhs.Equals( lhs ) );
+}
+
+/// operator< for lhs = StrongPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator < (
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
+{
+ return ( lhs.LessThan( rhs ) );
+}
+
+/// operator< for lhs = raw pointer, rhs = StrongPtr
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator < ( U * lhs,
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
+{
+ return ( rhs.GreaterThan( lhs ) );
+}
+
+// operator> for lhs = StrongPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator > (
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
+{
+ return ( lhs.GreaterThan( rhs ) );
+}
+
+/// operator> for lhs = raw pointer, rhs = StrongPtr
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator > ( U * lhs,
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
+{
+ return ( rhs.LessThan( lhs ) );
+}
+
+/// operator<= for lhs = StrongPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator <= (
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
+{
+ return !( lhs.GreaterThan( rhs ) );
+}
+
+/// operator<= for lhs = raw pointer, rhs = StrongPtr
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator <= ( U * lhs,
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
+{
+ return !( rhs.LessThan( lhs ) );
+}
+
+/// operator>= for lhs = StrongPtr, rhs = raw pointer
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator >= (
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
+{
+ return !( lhs.LessThan( rhs ) );
+}
+
+/// operator>= for lhs = raw pointer, rhs = StrongPtr
+/// \ingroup SmartPointerGroup
+template
+<
+ typename U,
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+>
+inline bool operator >= ( U * lhs,
+ const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
+{
+ return !( rhs.GreaterThan( lhs ) );
+}
+
+} // namespace Loki
+
+namespace std
+{
+ ////////////////////////////////////////////////////////////////////////////////
+ /// specialization of std::less for StrongPtr
+ /// \ingroup SmartPointerGroup
+ ////////////////////////////////////////////////////////////////////////////////
+ template
+ <
+ typename T,
+ bool S,
+ class OP,
+ class CP,
+ template < class > class KP,
+ template < class > class RP,
+ template < class > class DP,
+ template < class > class CNP
+ >
+ struct less< Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > >
+ : public binary_function<
+ Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >,
+ Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, bool >
+ {
+ bool operator () (
+ const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs,
+ const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) const
+ {
+ return ( lhs < rhs );
+ }
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // end file guardian
+
diff --git a/shared/loki/Threads.h b/shared/loki/Threads.h
new file mode 100644
index 00000000..cb44f094
--- /dev/null
+++ b/shared/loki/Threads.h
@@ -0,0 +1,609 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_THREADS_INC_
+#define LOKI_THREADS_INC_
+
+// $Id: Threads.h 902 2008-11-10 05:47:06Z rich_sposato $
+
+
+/// @defgroup ThreadingGroup Threading
+/// Policies to for the threading model:
+///
+/// - SingleThreaded
+/// - ObjectLevelLockable
+/// - ClassLevelLockable
+///
+/// All classes in Loki have configurable threading model.
+///
+/// The macro LOKI_DEFAULT_THREADING selects the default
+/// threading model for certain components of Loki
+/// (it affects only default template arguments)
+///
+/// \par Usage:
+///
+/// To use a specific threading model define
+///
+/// - nothing, single-theading is default
+/// - LOKI_OBJECT_LEVEL_THREADING for object-level-threading
+/// - LOKI_CLASS_LEVEL_THREADING for class-level-threading
+///
+/// \par Supported platfroms:
+///
+/// - Windows (windows.h)
+/// - POSIX (pthread.h):
+/// No recursive mutex support with pthread.
+/// This means: calling Lock() on a Loki::Mutex twice from the
+/// same thread before unlocking the mutex deadlocks the system.
+/// To avoid this redesign your synchronization. See also:
+/// http://sourceforge.net/tracker/index.php?func=detail&aid=1516182&group_id=29557&atid=396647
+
+
+#include <cassert>
+
+#if defined(LOKI_CLASS_LEVEL_THREADING) || defined(LOKI_OBJECT_LEVEL_THREADING)
+
+ #define LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL ::Loki::ClassLevelLockable
+
+ #if defined(LOKI_CLASS_LEVEL_THREADING) && !defined(LOKI_OBJECT_LEVEL_THREADING)
+ #define LOKI_DEFAULT_THREADING ::Loki::ClassLevelLockable
+ #else
+ #define LOKI_DEFAULT_THREADING ::Loki::ObjectLevelLockable
+ #endif
+
+ #if defined(_WIN32) || defined(_WIN64)
+ #include <windows.h>
+ #define LOKI_WINDOWS_H
+ #else
+ #include <pthread.h>
+ #define LOKI_PTHREAD_H
+ #endif
+
+#else
+
+ #define LOKI_DEFAULT_THREADING ::Loki::SingleThreaded
+ #define LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL ::Loki::SingleThreaded
+
+#endif
+
+#ifndef LOKI_DEFAULT_MUTEX
+#define LOKI_DEFAULT_MUTEX ::Loki::Mutex
+#endif
+
+#ifdef LOKI_WINDOWS_H
+
+#define LOKI_THREADS_MUTEX(x) CRITICAL_SECTION (x);
+#define LOKI_THREADS_MUTEX_INIT(x) ::InitializeCriticalSection (x)
+#define LOKI_THREADS_MUTEX_DELETE(x) ::DeleteCriticalSection (x)
+#define LOKI_THREADS_MUTEX_LOCK(x) ::EnterCriticalSection (x)
+#define LOKI_THREADS_MUTEX_UNLOCK(x) ::LeaveCriticalSection (x)
+#define LOKI_THREADS_LONG LONG
+#define LOKI_THREADS_MUTEX_CTOR(x)
+
+#define LOKI_THREADS_ATOMIC_FUNCTIONS \
+ static IntType AtomicMultiply(volatile IntType& lval, const IntType val) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ lval *= val; \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicDivide(volatile IntType& lval, const IntType val) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ lval /= val; \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicIncrement(volatile IntType& lval) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ ++lval; \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicDecrement(volatile IntType& lval) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ --lval; \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static void AtomicAssign(volatile IntType& lval, const IntType val) \
+ { InterlockedExchange(&const_cast<IntType&>(lval), val); } \
+ \
+ static void AtomicAssign(IntType& lval, volatile const IntType& val) \
+ { InterlockedExchange(&lval, val); } \
+ \
+ static IntType AtomicIncrement(volatile IntType& lval, const IntType compare, bool & matches ) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ ++lval; \
+ matches = ( lval == compare ); \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicDecrement(volatile IntType& lval, const IntType compare, bool & matches ) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ --lval; \
+ matches = ( lval == compare ); \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicAdd(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ lval += val; \
+ matches = ( lval == compare ); \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicSubtract(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ lval -= val; \
+ matches = ( lval == compare ); \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicMultiply(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ lval *= val; \
+ matches = ( lval == compare ); \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicDivide(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \
+ { \
+ ::EnterCriticalSection( &atomic_mutex_ ); \
+ lval /= val; \
+ matches = ( lval == compare ); \
+ ::LeaveCriticalSection( &atomic_mutex_ ); \
+ return lval; \
+ }
+
+#elif defined(LOKI_PTHREAD_H)
+
+
+#define LOKI_THREADS_MUTEX(x) pthread_mutex_t (x);
+
+#define LOKI_THREADS_MUTEX_INIT(x) ::pthread_mutex_init(x, 0)
+
+// define to 1 to enable recursive mutex support
+#if 0
+// experimental recursive mutex support
+#define LOKI_THREADS_MUTEX_CTOR(x) : x(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
+#else
+// no recursive mutex support
+#define LOKI_THREADS_MUTEX_CTOR(x)
+#endif
+
+#define LOKI_THREADS_MUTEX_DELETE(x) ::pthread_mutex_destroy (x)
+#define LOKI_THREADS_MUTEX_LOCK(x) ::pthread_mutex_lock (x)
+#define LOKI_THREADS_MUTEX_UNLOCK(x) ::pthread_mutex_unlock (x)
+#define LOKI_THREADS_LONG long
+
+#define LOKI_THREADS_ATOMIC(x) \
+ pthread_mutex_lock(&atomic_mutex_); \
+ x; \
+ pthread_mutex_unlock(&atomic_mutex_)
+
+#define LOKI_THREADS_ATOMIC_FUNCTIONS \
+ private: \
+ static pthread_mutex_t atomic_mutex_; \
+ public: \
+ static IntType AtomicMultiply(volatile IntType& lval, const IntType val) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ lval *= val; \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicDivide(volatile IntType& lval, const IntType val) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ lval /= val; \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicIncrement(volatile IntType& lval) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ ++lval; \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicDecrement(volatile IntType& lval) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ --lval; \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static void AtomicAssign(volatile IntType& lval, const IntType val) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ lval = val; \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static void AtomicAssign(IntType& lval, volatile const IntType& val) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ lval = val; \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicIncrement(volatile IntType& lval, const IntType compare, bool & matches ) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ ++lval; \
+ matches = ( compare == lval ); \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicDecrement(volatile IntType& lval, const IntType compare, bool & matches ) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ --lval; \
+ matches = ( compare == lval ); \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ static IntType AtomicMultiply(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ lval *= val; \
+ matches = ( lval == compare ); \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ } \
+ \
+ static IntType AtomicDivide(volatile IntType& lval, const IntType val, const IntType compare, bool & matches ) \
+ { \
+ ::pthread_mutex_lock( &atomic_mutex_ ); \
+ lval /= val; \
+ matches = ( lval == compare ); \
+ ::pthread_mutex_unlock( &atomic_mutex_ ); \
+ return lval; \
+ }
+
+#else // single threaded
+
+#define LOKI_THREADS_MUTEX(x)
+#define LOKI_THREADS_MUTEX_INIT(x)
+#define LOKI_THREADS_MUTEX_DELETE(x)
+#define LOKI_THREADS_MUTEX_LOCK(x)
+#define LOKI_THREADS_MUTEX_UNLOCK(x)
+#define LOKI_THREADS_LONG
+#define LOKI_THREADS_MUTEX_CTOR(x)
+
+#endif
+
+
+
+namespace Loki
+{
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class Mutex
+ //
+ /// \ingroup ThreadingGroup
+ /// A simple and portable Mutex. A default policy class for locking objects.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ class Mutex
+ {
+ public:
+ Mutex() LOKI_THREADS_MUTEX_CTOR(mtx_)
+ {
+ LOKI_THREADS_MUTEX_INIT(&mtx_);
+ }
+ ~Mutex()
+ {
+ LOKI_THREADS_MUTEX_DELETE(&mtx_);
+ }
+ void Lock()
+ {
+ LOKI_THREADS_MUTEX_LOCK(&mtx_);
+ }
+ void Unlock()
+ {
+ LOKI_THREADS_MUTEX_UNLOCK(&mtx_);
+ }
+ private:
+ /// Copy-constructor not implemented.
+ Mutex(const Mutex &);
+ /// Copy-assignement operator not implemented.
+ Mutex & operator = (const Mutex &);
+ LOKI_THREADS_MUTEX(mtx_)
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class SingleThreaded
+ ///
+ /// \ingroup ThreadingGroup
+ /// Implementation of the ThreadingModel policy used by various classes
+ /// Implements a single-threaded model; no synchronization
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class Host, class MutexPolicy = LOKI_DEFAULT_MUTEX>
+ class SingleThreaded
+ {
+ public:
+ /// \struct Lock
+ /// Dummy Lock class
+ struct Lock
+ {
+ Lock() {}
+ explicit Lock(const SingleThreaded&) {}
+ explicit Lock(const SingleThreaded*) {}
+ };
+
+ typedef Host VolatileType;
+
+ typedef int IntType;
+
+ static IntType AtomicAdd(volatile IntType& lval, const IntType val)
+ { return lval += val; }
+
+ static IntType AtomicSubtract(volatile IntType& lval, const IntType val)
+ { return lval -= val; }
+
+ static IntType AtomicMultiply(volatile IntType& lval, const IntType val)
+ { return lval *= val; }
+
+ static IntType AtomicDivide(volatile IntType& lval, const IntType val)
+ { return lval /= val; }
+
+ static IntType AtomicIncrement(volatile IntType& lval)
+ { return ++lval; }
+
+ static IntType AtomicDecrement(volatile IntType& lval)
+ { return --lval; }
+
+ static void AtomicAssign(volatile IntType & lval, const IntType val)
+ { lval = val; }
+
+ static void AtomicAssign(IntType & lval, volatile IntType & val)
+ { lval = val; }
+
+ static IntType AtomicAdd(volatile IntType& lval, const IntType val, const IntType compare, bool & matches )
+ {
+ lval += val;
+ matches = ( lval == compare );
+ return lval;
+ }
+
+ static IntType AtomicSubtract(volatile IntType& lval, const IntType val, const IntType compare, bool & matches )
+ {
+ lval -= val;
+ matches = ( lval == compare );
+ return lval;
+ }
+
+ static IntType AtomicMultiply(volatile IntType& lval, const IntType val, const IntType compare, bool & matches )
+ {
+ lval *= val;
+ matches = ( lval == compare );
+ return lval;
+ }
+
+ static IntType AtomicDivide(volatile IntType& lval, const IntType val, const IntType compare, bool & matches )
+ {
+ lval /= val;
+ matches = ( lval == compare );
+ return lval;
+ }
+
+ static IntType AtomicIncrement(volatile IntType& lval, const IntType compare, bool & matches )
+ {
+ ++lval;
+ matches = ( lval == compare );
+ return lval;
+ }
+
+ static IntType AtomicDecrement(volatile IntType& lval, const IntType compare, bool & matches )
+ {
+ --lval;
+ matches = ( lval == compare );
+ return lval;
+ }
+
+ };
+
+
+#if defined(LOKI_WINDOWS_H) || defined(LOKI_PTHREAD_H)
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class ObjectLevelLockable
+ ///
+ /// \ingroup ThreadingGroup
+ /// Implementation of the ThreadingModel policy used by various classes
+ /// Implements a object-level locking scheme
+ ////////////////////////////////////////////////////////////////////////////////
+ template < class Host, class MutexPolicy = LOKI_DEFAULT_MUTEX >
+ class ObjectLevelLockable
+ {
+ mutable MutexPolicy mtx_;
+
+ public:
+ ObjectLevelLockable() : mtx_() {}
+
+ ObjectLevelLockable(const ObjectLevelLockable&) : mtx_() {}
+
+ ~ObjectLevelLockable() {}
+
+ class Lock;
+ friend class Lock;
+
+ /// \struct Lock
+ /// Lock class to lock on object level
+ class Lock
+ {
+ public:
+
+ /// Lock object
+ explicit Lock(const ObjectLevelLockable& host) : host_(host)
+ {
+ host_.mtx_.Lock();
+ }
+
+ /// Lock object
+ explicit Lock(const ObjectLevelLockable* host) : host_(*host)
+ {
+ host_.mtx_.Lock();
+ }
+
+ /// Unlock object
+ ~Lock()
+ {
+ host_.mtx_.Unlock();
+ }
+
+ private:
+ /// private by design of the object level threading
+ Lock();
+ Lock(const Lock&);
+ Lock& operator=(const Lock&);
+ const ObjectLevelLockable& host_;
+ };
+
+ typedef volatile Host VolatileType;
+
+ typedef LOKI_THREADS_LONG IntType;
+
+ LOKI_THREADS_ATOMIC_FUNCTIONS
+
+ };
+
+#ifdef LOKI_PTHREAD_H
+ template <class Host, class MutexPolicy>
+ pthread_mutex_t ObjectLevelLockable<Host, MutexPolicy>::atomic_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class ClassLevelLockable
+ ///
+ /// \ingroup ThreadingGroup
+ /// Implementation of the ThreadingModel policy used by various classes
+ /// Implements a class-level locking scheme
+ ////////////////////////////////////////////////////////////////////////////////
+ template <class Host, class MutexPolicy = LOKI_DEFAULT_MUTEX >
+ class ClassLevelLockable
+ {
+ struct Initializer
+ {
+ bool init_;
+ MutexPolicy mtx_;
+
+ Initializer() : init_(false), mtx_()
+ {
+ init_ = true;
+ }
+
+ ~Initializer()
+ {
+ assert(init_);
+ }
+ };
+
+ static Initializer initializer_;
+
+ public:
+
+ class Lock;
+ friend class Lock;
+
+ /// \struct Lock
+ /// Lock class to lock on class level
+ class Lock
+ {
+ public:
+
+ /// Lock class
+ Lock()
+ {
+ assert(initializer_.init_);
+ initializer_.mtx_.Lock();
+ }
+
+ /// Lock class
+ explicit Lock(const ClassLevelLockable&)
+ {
+ assert(initializer_.init_);
+ initializer_.mtx_.Lock();
+ }
+
+ /// Lock class
+ explicit Lock(const ClassLevelLockable*)
+ {
+ assert(initializer_.init_);
+ initializer_.mtx_.Lock();
+ }
+
+ /// Unlock class
+ ~Lock()
+ {
+ assert(initializer_.init_);
+ initializer_.mtx_.Unlock();
+ }
+
+ private:
+ Lock(const Lock&);
+ Lock& operator=(const Lock&);
+ };
+
+ typedef volatile Host VolatileType;
+
+ typedef LOKI_THREADS_LONG IntType;
+
+ LOKI_THREADS_ATOMIC_FUNCTIONS
+
+ };
+
+#ifdef LOKI_PTHREAD_H
+ template <class Host, class MutexPolicy>
+ pthread_mutex_t ClassLevelLockable<Host, MutexPolicy>::atomic_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+ template < class Host, class MutexPolicy >
+ typename ClassLevelLockable< Host, MutexPolicy >::Initializer
+ ClassLevelLockable< Host, MutexPolicy >::initializer_;
+
+#endif // #if defined(LOKI_WINDOWS_H) || defined(LOKI_PTHREAD_H)
+
+} // namespace Loki
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/Tuple.h b/shared/loki/Tuple.h
new file mode 100644
index 00000000..47fc19e2
--- /dev/null
+++ b/shared/loki/Tuple.h
@@ -0,0 +1,22 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+
+// Last update: June 20, 2001
+
+////////////////////////////////////////////////////////////////////////////////
+// This file is intentionally left empty
+// Due to compiler limitations, its contents has been moved to
+// HierarchyGenerators.h
+////////////////////////////////////////////////////////////////////////////////
diff --git a/shared/loki/TypeManip.h b/shared/loki/TypeManip.h
new file mode 100644
index 00000000..e08b4e03
--- /dev/null
+++ b/shared/loki/TypeManip.h
@@ -0,0 +1,284 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Welsey Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_TYPEMANIP_INC_
+#define LOKI_TYPEMANIP_INC_
+
+// $Id: TypeManip.h 749 2006-10-17 19:49:26Z syntheticpp $
+
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class template Int2Type
+// Converts each integral constant into a unique type
+// Invocation: Int2Type<v> where v is a compile-time constant integral
+// Defines 'value', an enum that evaluates to v
+////////////////////////////////////////////////////////////////////////////////
+
+ template <int v>
+ struct Int2Type
+ {
+ enum { value = v };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Type2Type
+// Converts each type into a unique, insipid type
+// Invocation Type2Type<T> where T is a type
+// Defines the type OriginalType which maps back to T
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename T>
+ struct Type2Type
+ {
+ typedef T OriginalType;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Select
+// Selects one of two types based upon a boolean constant
+// Invocation: Select<flag, T, U>::Result
+// where:
+// flag is a compile-time boolean constant
+// T and U are types
+// Result evaluates to T if flag is true, and to U otherwise.
+////////////////////////////////////////////////////////////////////////////////
+
+ template <bool flag, typename T, typename U>
+ struct Select
+ {
+ typedef T Result;
+ };
+ template <typename T, typename U>
+ struct Select<false, T, U>
+ {
+ typedef U Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template IsSameType
+// Return true iff two given types are the same
+// Invocation: SameType<T, U>::value
+// where:
+// T and U are types
+// Result evaluates to true iff U == T (types equal)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename T, typename U>
+ struct IsSameType
+ {
+ enum { value = false };
+ };
+
+ template <typename T>
+ struct IsSameType<T,T>
+ {
+ enum { value = true };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+ template <class T, class U>
+ struct ConversionHelper
+ {
+ typedef char Small;
+ struct Big { char dummy[2]; };
+ static Big Test(...);
+ static Small Test(U);
+ static T MakeT();
+ };
+ }
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Conversion
+// Figures out the conversion relationships between two types
+// Invocations (T and U are types):
+// a) Conversion<T, U>::exists
+// returns (at compile time) true if there is an implicit conversion from T
+// to U (example: Derived to Base)
+// b) Conversion<T, U>::exists2Way
+// returns (at compile time) true if there are both conversions from T
+// to U and from U to T (example: int to char and back)
+// c) Conversion<T, U>::sameType
+// returns (at compile time) true if T and U represent the same type
+//
+// Caveat: might not work if T and U are in a private inheritance hierarchy.
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T, class U>
+ struct Conversion
+ {
+ typedef Private::ConversionHelper<T, U> H;
+#ifndef __MWERKS__
+ enum { exists = sizeof(typename H::Small) == sizeof((H::Test(H::MakeT()))) };
+#else
+ enum { exists = false };
+#endif
+ enum { exists2Way = exists && Conversion<U, T>::exists };
+ enum { sameType = false };
+ };
+
+ template <class T>
+ struct Conversion<T, T>
+ {
+ enum { exists = 1, exists2Way = 1, sameType = 1 };
+ };
+
+ template <class T>
+ struct Conversion<void, T>
+ {
+ enum { exists = 0, exists2Way = 0, sameType = 0 };
+ };
+
+ template <class T>
+ struct Conversion<T, void>
+ {
+ enum { exists = 0, exists2Way = 0, sameType = 0 };
+ };
+
+ template <>
+ struct Conversion<void, void>
+ {
+ public:
+ enum { exists = 1, exists2Way = 1, sameType = 1 };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template SuperSubclass
+// Invocation: SuperSubclass<B, D>::value where B and D are types.
+// Returns true if B is a public base of D, or if B and D are aliases of the
+// same type.
+//
+// Caveat: might not work if T and U are in a private inheritance hierarchy.
+////////////////////////////////////////////////////////////////////////////////
+
+template <class T, class U>
+struct SuperSubclass
+{
+ enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
+ !::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
+
+ // Dummy enum to make sure that both classes are fully defined.
+ enum{ dontUseWithIncompleteTypes = ( sizeof (T) == sizeof (U) ) };
+};
+
+template <>
+struct SuperSubclass<void, void>
+{
+ enum { value = false };
+};
+
+template <class U>
+struct SuperSubclass<void, U>
+{
+ enum { value = (::Loki::Conversion<const volatile U*, const volatile void*>::exists &&
+ !::Loki::Conversion<const volatile void*, const volatile void*>::sameType) };
+
+ // Dummy enum to make sure that both classes are fully defined.
+ enum{ dontUseWithIncompleteTypes = ( 0 == sizeof (U) ) };
+};
+
+template <class T>
+struct SuperSubclass<T, void>
+{
+ enum { value = (::Loki::Conversion<const volatile void*, const volatile T*>::exists &&
+ !::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
+
+ // Dummy enum to make sure that both classes are fully defined.
+ enum{ dontUseWithIncompleteTypes = ( sizeof (T) == 0 ) };
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// class template SuperSubclassStrict
+// Invocation: SuperSubclassStrict<B, D>::value where B and D are types.
+// Returns true if B is a public base of D.
+//
+// Caveat: might not work if T and U are in a private inheritance hierarchy.
+////////////////////////////////////////////////////////////////////////////////
+
+template<class T,class U>
+struct SuperSubclassStrict
+{
+ enum { value = (::Loki::Conversion<const volatile U*, const volatile T*>::exists &&
+ !::Loki::Conversion<const volatile T*, const volatile void*>::sameType &&
+ !::Loki::Conversion<const volatile T*, const volatile U*>::sameType) };
+
+ // Dummy enum to make sure that both classes are fully defined.
+ enum{ dontUseWithIncompleteTypes = ( sizeof (T) == sizeof (U) ) };
+};
+
+template<>
+struct SuperSubclassStrict<void, void>
+{
+ enum { value = false };
+};
+
+template<class U>
+struct SuperSubclassStrict<void, U>
+{
+ enum { value = (::Loki::Conversion<const volatile U*, const volatile void*>::exists &&
+ !::Loki::Conversion<const volatile void*, const volatile void*>::sameType &&
+ !::Loki::Conversion<const volatile void*, const volatile U*>::sameType) };
+
+ // Dummy enum to make sure that both classes are fully defined.
+ enum{ dontUseWithIncompleteTypes = ( 0 == sizeof (U) ) };
+};
+
+template<class T>
+struct SuperSubclassStrict<T, void>
+{
+ enum { value = (::Loki::Conversion<const volatile void*, const volatile T*>::exists &&
+ !::Loki::Conversion<const volatile T*, const volatile void*>::sameType &&
+ !::Loki::Conversion<const volatile T*, const volatile void*>::sameType) };
+
+ // Dummy enum to make sure that both classes are fully defined.
+ enum{ dontUseWithIncompleteTypes = ( sizeof (T) == 0 ) };
+};
+
+
+} // namespace Loki
+
+////////////////////////////////////////////////////////////////////////////////
+// macro SUPERSUBCLASS
+// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
+// Returns true if B is a public base of D, or if B and D are aliases of the
+// same type.
+//
+// Caveat: might not work if T and U are in a private inheritance hierarchy.
+// Deprecated: Use SuperSubclass class template instead.
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_SUPERSUBCLASS(T, U) \
+ ::Loki::SuperSubclass<T,U>::value
+
+////////////////////////////////////////////////////////////////////////////////
+// macro SUPERSUBCLASS_STRICT
+// Invocation: SUPERSUBCLASS(B, D) where B and D are types.
+// Returns true if B is a public base of D.
+//
+// Caveat: might not work if T and U are in a private inheritance hierarchy.
+// Deprecated: Use SuperSubclassStrict class template instead.
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_SUPERSUBCLASS_STRICT(T, U) \
+ ::Loki::SuperSubclassStrict<T,U>::value
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/TypeTraits.h b/shared/loki/TypeTraits.h
new file mode 100644
index 00000000..a592cab9
--- /dev/null
+++ b/shared/loki/TypeTraits.h
@@ -0,0 +1,2228 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_TYPETRAITS_INC_
+#define LOKI_TYPETRAITS_INC_
+
+// $Id: TypeTraits.h 835 2007-08-02 19:39:02Z syntheticpp $
+
+
+#include "Typelist.h"
+#include "Sequence.h"
+
+#if (defined _MSC_VER) && (_MSC_VER < 1400)
+#include <string>
+#endif
+
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4180 ) //qualifier applied to function type has no meaning; ignored
+#endif
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class template IsCustomUnsignedInt
+// Offers a means to integrate nonstandard built-in unsigned integral types
+// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
+// class template defined below.
+// Invocation: IsCustomUnsignedInt<T> where T is any type
+// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned
+// integral type
+// Specialize this class template for nonstandard unsigned integral types
+// and define value = 1 in those specializations
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename T>
+ struct IsCustomUnsignedInt
+ {
+ enum { value = 0 };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template IsCustomSignedInt
+// Offers a means to integrate nonstandard built-in unsigned integral types
+// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
+// class template defined below.
+// Invocation: IsCustomSignedInt<T> where T is any type
+// Defines 'value', an enum that is 1 iff T is a custom built-in signed
+// integral type
+// Specialize this class template for nonstandard unsigned integral types
+// and define value = 1 in those specializations
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename T>
+ struct IsCustomSignedInt
+ {
+ enum { value = 0 };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template IsCustomFloat
+// Offers a means to integrate nonstandard floating point types with the
+// TypeTraits class template defined below.
+// Invocation: IsCustomFloat<T> where T is any type
+// Defines 'value', an enum that is 1 iff T is a custom built-in
+// floating point type
+// Specialize this class template for nonstandard unsigned integral types
+// and define value = 1 in those specializations
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename T>
+ struct IsCustomFloat
+ {
+ enum { value = 0 };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper types for class template TypeTraits defined below
+////////////////////////////////////////////////////////////////////////////////
+
+ namespace Private
+ {
+#ifndef LOKI_DISABLE_TYPELIST_MACROS
+ typedef LOKI_TYPELIST_4(unsigned char, unsigned short int,unsigned int, unsigned long int)
+ StdUnsignedInts;
+ typedef LOKI_TYPELIST_4(signed char, short int,int, long int)
+ StdSignedInts;
+ typedef LOKI_TYPELIST_3(bool, char, wchar_t)
+ StdOtherInts;
+ typedef LOKI_TYPELIST_3(float, double, long double)
+ StdFloats;
+#else
+ typedef Loki::Seq<unsigned char, unsigned short int,unsigned int, unsigned long int>::Type
+ StdUnsignedInts;
+ typedef Loki::Seq<signed char, short int,int, long int>::Type
+ StdSignedInts;
+ typedef Loki::Seq<bool, char, wchar_t>::Type
+ StdOtherInts;
+ typedef Loki::Seq<float, double, long double>::Type
+ StdFloats;
+
+#endif
+ template <typename U> struct AddPointer
+ {
+ typedef U* Result;
+ };
+
+ template <typename U> struct AddPointer<U&>
+ {
+ typedef U* Result;
+ };
+
+ template <class U> struct AddReference
+ {
+ typedef U & Result;
+ };
+
+ template <class U> struct AddReference<U &>
+ {
+ typedef U & Result;
+ };
+
+ template <> struct AddReference<void>
+ {
+ typedef NullType Result;
+ };
+
+ template <class U> struct AddParameterType
+ {
+ typedef const U & Result;
+ };
+
+ template <class U> struct AddParameterType<U &>
+ {
+ typedef U & Result;
+ };
+
+ template <> struct AddParameterType<void>
+ {
+ typedef NullType Result;
+ };
+
+ template <typename T>
+ struct IsFunctionPointerRaw
+ {enum{result = 0};};
+
+ template <typename T>
+ struct IsFunctionPointerRaw<T(*)()>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01>
+ struct IsFunctionPointerRaw<T(*)(P01)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20)>
+ {enum {result = 1};};
+
+ template <typename T>
+ struct IsFunctionPointerRaw<T(*)(
+ ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, ...)>
+ {enum {result = 1};};
+
+ template <typename T,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsFunctionPointerRaw<T(*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20,
+ ...)>
+ {enum {result = 1};};
+
+
+ template <typename T>
+ struct IsMemberFunctionPointerRaw
+ {enum{result = 0};};
+
+ template <typename T, typename S>
+ struct IsMemberFunctionPointerRaw<T (S::*)()>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01>
+ struct IsMemberFunctionPointerRaw<T (S::*)(P01)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20)>
+ {enum {result = 1};};
+
+ template <typename T, typename S>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, ...)>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20,
+ ...)>
+ {enum {result = 1};};
+
+ // Const versions
+
+ template <typename T, typename S>
+ struct IsMemberFunctionPointerRaw<T (S::*)() const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01>
+ struct IsMemberFunctionPointerRaw<T (S::*)(P01) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, ...) const>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20,
+ ...) const>
+ {enum {result = 1};};
+
+ // Volatile versions
+
+ template <typename T, typename S>
+ struct IsMemberFunctionPointerRaw<T (S::*)() volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01>
+ struct IsMemberFunctionPointerRaw<T (S::*)(P01) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, ...) volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20,
+ ...) volatile>
+ {enum {result = 1};};
+
+ // Const volatile versions
+
+ template <typename T, typename S>
+ struct IsMemberFunctionPointerRaw<T (S::*)() const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01>
+ struct IsMemberFunctionPointerRaw<T (S::*)(P01) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, ...) const volatile>
+ {enum {result = 1};};
+
+ template <typename T, typename S,
+ typename P01, typename P02, typename P03, typename P04, typename P05,
+ typename P06, typename P07, typename P08, typename P09, typename P10,
+ typename P11, typename P12, typename P13, typename P14, typename P15,
+ typename P16, typename P17, typename P18, typename P19, typename P20>
+ struct IsMemberFunctionPointerRaw<T (S::*)(
+ P01, P02, P03, P04, P05,
+ P06, P07, P08, P09, P10,
+ P11, P12, P13, P14, P15,
+ P16, P17, P18, P19, P20,
+ ...) const volatile>
+ {enum {result = 1};};
+
+ }// namespace Private
+
+////////////////////////////////////////////////////////////////////////////////
+// class template TypeTraits
+//
+// Figures out at compile time various properties of any given type
+// Invocations (T is a type, TypeTraits<T>::Property):
+//
+// - isPointer : returns true if T is a pointer type
+// - PointeeType : returns the type to which T points if T is a pointer
+// type, NullType otherwise
+// - isReference : returns true if T is a reference type
+// - ReferredType : returns the type to which T refers if T is a reference
+// type, NullType otherwise
+// - isMemberPointer : returns true if T is a pointer to member type
+// - isStdUnsignedInt: returns true if T is a standard unsigned integral type
+// - isStdSignedInt : returns true if T is a standard signed integral type
+// - isStdIntegral : returns true if T is a standard integral type
+// - isStdFloat : returns true if T is a standard floating-point type
+// - isStdArith : returns true if T is a standard arithmetic type
+// - isStdFundamental: returns true if T is a standard fundamental type
+// - isUnsignedInt : returns true if T is a unsigned integral type
+// - isSignedInt : returns true if T is a signed integral type
+// - isIntegral : returns true if T is a integral type
+// - isFloat : returns true if T is a floating-point type
+// - isArith : returns true if T is a arithmetic type
+// - isFundamental : returns true if T is a fundamental type
+// - ParameterType : returns the optimal type to be used as a parameter for
+// functions that take Ts
+// - isConst : returns true if T is a const-qualified type
+// - NonConstType : Type with removed 'const' qualifier from T, if any
+// - isVolatile : returns true if T is a volatile-qualified type
+// - NonVolatileType : Type with removed 'volatile' qualifier from T, if any
+// - UnqualifiedType : Type with removed 'const' and 'volatile' qualifiers from
+// T, if any
+// - ParameterType : returns the optimal type to be used as a parameter
+// for functions that take 'const T's
+//
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename T>
+ class TypeTraits
+ {
+ private:
+
+ template <class U> struct ReferenceTraits
+ {
+ enum { result = false };
+ typedef U ReferredType;
+ };
+
+ template <class U> struct ReferenceTraits<U&>
+ {
+ enum { result = true };
+ typedef U ReferredType;
+ };
+
+ template <class U> struct PointerTraits
+ {
+ enum { result = false };
+ typedef NullType PointeeType;
+ };
+
+ template <class U> struct PointerTraits<U*>
+ {
+ enum { result = true };
+ typedef U PointeeType;
+ };
+
+ template <class U> struct PointerTraits<U*&>
+ {
+ enum { result = true };
+ typedef U PointeeType;
+ };
+
+ template <class U> struct PToMTraits
+ {
+ enum { result = false };
+ };
+
+ template <class U, class V> struct PToMTraits<U V::*>
+ {
+ enum { result = true };
+ };
+
+ template <class U, class V> struct PToMTraits<U V::*&>
+ {
+ enum { result = true };
+ };
+
+ template <class U> struct FunctionPointerTraits
+ {
+ enum{ result = Private::IsFunctionPointerRaw<U>::result };
+ };
+
+ template <typename U> struct PToMFunctionTraits
+ {
+ enum{ result = Private::IsMemberFunctionPointerRaw<U>::result };
+ };
+
+ template <class U> struct UnConst
+ {
+ typedef U Result;
+ enum { isConst = 0 };
+ };
+
+ template <class U> struct UnConst<const U>
+ {
+ typedef U Result;
+ enum { isConst = 1 };
+ };
+
+ template <class U> struct UnConst<const U&>
+ {
+ typedef U& Result;
+ enum { isConst = 1 };
+ };
+
+ template <class U> struct UnVolatile
+ {
+ typedef U Result;
+ enum { isVolatile = 0 };
+ };
+
+ template <class U> struct UnVolatile<volatile U>
+ {
+ typedef U Result;
+ enum { isVolatile = 1 };
+ };
+
+ template <class U> struct UnVolatile<volatile U&>
+ {
+ typedef U& Result;
+ enum { isVolatile = 1 };
+ };
+
+ public:
+ typedef typename UnConst<T>::Result
+ NonConstType;
+ typedef typename UnVolatile<T>::Result
+ NonVolatileType;
+ typedef typename UnVolatile<typename UnConst<T>::Result>::Result
+ UnqualifiedType;
+ typedef typename PointerTraits<UnqualifiedType>::PointeeType
+ PointeeType;
+ typedef typename ReferenceTraits<T>::ReferredType
+ ReferredType;
+
+ enum { isConst = UnConst<T>::isConst };
+ enum { isVolatile = UnVolatile<T>::isVolatile };
+ enum { isReference = ReferenceTraits<UnqualifiedType>::result };
+ enum { isFunction = FunctionPointerTraits<typename Private::AddPointer<T>::Result >::result };
+ enum { isFunctionPointer= FunctionPointerTraits<
+ typename ReferenceTraits<UnqualifiedType>::ReferredType >::result };
+ enum { isMemberFunctionPointer= PToMFunctionTraits<
+ typename ReferenceTraits<UnqualifiedType>::ReferredType >::result };
+ enum { isMemberPointer = PToMTraits<
+ typename ReferenceTraits<UnqualifiedType>::ReferredType >::result ||
+ isMemberFunctionPointer };
+ enum { isPointer = PointerTraits<
+ typename ReferenceTraits<UnqualifiedType>::ReferredType >::result ||
+ isFunctionPointer };
+
+ enum { isStdUnsignedInt = TL::IndexOf<Private::StdUnsignedInts, UnqualifiedType>::value >= 0 ||
+ TL::IndexOf<Private::StdUnsignedInts,
+ typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0};
+ enum { isStdSignedInt = TL::IndexOf<Private::StdSignedInts, UnqualifiedType>::value >= 0 ||
+ TL::IndexOf<Private::StdSignedInts,
+ typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0};
+ enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt ||
+ TL::IndexOf<Private::StdOtherInts, UnqualifiedType>::value >= 0 ||
+ TL::IndexOf<Private::StdOtherInts,
+ typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0};
+ enum { isStdFloat = TL::IndexOf<Private::StdFloats, UnqualifiedType>::value >= 0 ||
+ TL::IndexOf<Private::StdFloats,
+ typename ReferenceTraits<UnqualifiedType>::ReferredType>::value >= 0};
+ enum { isStdArith = isStdIntegral || isStdFloat };
+ enum { isStdFundamental = isStdArith || isStdFloat || Conversion<T, void>::sameType };
+
+ enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt<UnqualifiedType>::value };
+ enum { isSignedInt = isStdSignedInt || IsCustomSignedInt<UnqualifiedType>::value };
+ enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt };
+ enum { isFloat = isStdFloat || IsCustomFloat<UnqualifiedType>::value };
+ enum { isArith = isIntegral || isFloat };
+ enum { isFundamental = isStdFundamental || isArith };
+
+ typedef typename Select<isStdArith || isPointer || isMemberPointer, T,
+ typename Private::AddParameterType<T>::Result>::Result
+ ParameterType;
+ };
+}
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif // _MSC_VER
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/Typelist.h b/shared/loki/Typelist.h
new file mode 100644
index 00000000..6a885927
--- /dev/null
+++ b/shared/loki/Typelist.h
@@ -0,0 +1,459 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Welsey Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_TYPELIST_INC_
+#define LOKI_TYPELIST_INC_
+
+// $Id: Typelist.h 749 2006-10-17 19:49:26Z syntheticpp $
+
+
+#include "NullType.h"
+#include "TypeManip.h"
+#include "TypelistMacros.h"
+
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class template Typelist
+// The building block of typelists of any length
+// Use it through the LOKI_TYPELIST_NN macros
+// Defines nested types:
+// Head (first element, a non-typelist type by convention)
+// Tail (second element, can be another typelist)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T, class U>
+ struct Typelist
+ {
+ typedef T Head;
+ typedef U Tail;
+ };
+
+// Typelist utility algorithms
+
+ namespace TL
+ {
+
+////////////////////////////////////////////////////////////////////////////////
+// class template MakeTypelist
+// Takes a number of arguments equal to its numeric suffix
+// The arguments are type names.
+// MakeTypelist<T1, T2, ...>::Result
+// returns a typelist that is of T1, T2, ...
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename T1 = NullType, typename T2 = NullType, typename T3 = NullType,
+ typename T4 = NullType, typename T5 = NullType, typename T6 = NullType,
+ typename T7 = NullType, typename T8 = NullType, typename T9 = NullType,
+ typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
+ typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
+ typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
+ >
+ struct MakeTypelist
+ {
+ private:
+ typedef typename MakeTypelist
+ <
+ T2 , T3 , T4 ,
+ T5 , T6 , T7 ,
+ T8 , T9 , T10,
+ T11, T12, T13,
+ T14, T15, T16,
+ T17, T18
+ >
+ ::Result TailResult;
+
+ public:
+ typedef Typelist<T1, TailResult> Result;
+ };
+
+ template<>
+ struct MakeTypelist<>
+ {
+ typedef NullType Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Length
+// Computes the length of a typelist
+// Invocation (TList is a typelist):
+// Length<TList>::value
+// returns a compile-time constant containing the length of TList, not counting
+// the end terminator (which by convention is NullType)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList> struct Length;
+ template <> struct Length<NullType>
+ {
+ enum { value = 0 };
+ };
+
+ template <class T, class U>
+ struct Length< Typelist<T, U> >
+ {
+ enum { value = 1 + Length<U>::value };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template TypeAt
+// Finds the type at a given index in a typelist
+// Invocation (TList is a typelist and index is a compile-time integral
+// constant):
+// TypeAt<TList, index>::Result
+// returns the type in position 'index' in TList
+// If you pass an out-of-bounds index, the result is a compile-time error
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, unsigned int index> struct TypeAt;
+
+ template <class Head, class Tail>
+ struct TypeAt<Typelist<Head, Tail>, 0>
+ {
+ typedef Head Result;
+ };
+
+ template <class Head, class Tail, unsigned int i>
+ struct TypeAt<Typelist<Head, Tail>, i>
+ {
+ typedef typename TypeAt<Tail, i - 1>::Result Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template TypeAtNonStrict
+// Finds the type at a given index in a typelist
+// Invocations (TList is a typelist and index is a compile-time integral
+// constant):
+// a) TypeAt<TList, index>::Result
+// returns the type in position 'index' in TList, or NullType if index is
+// out-of-bounds
+// b) TypeAt<TList, index, D>::Result
+// returns the type in position 'index' in TList, or D if index is out-of-bounds
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, unsigned int index,
+ typename DefaultType = NullType>
+ struct TypeAtNonStrict
+ {
+ typedef DefaultType Result;
+ };
+
+ template <class Head, class Tail, typename DefaultType>
+ struct TypeAtNonStrict<Typelist<Head, Tail>, 0, DefaultType>
+ {
+ typedef Head Result;
+ };
+
+ template <class Head, class Tail, unsigned int i, typename DefaultType>
+ struct TypeAtNonStrict<Typelist<Head, Tail>, i, DefaultType>
+ {
+ typedef typename
+ TypeAtNonStrict<Tail, i - 1, DefaultType>::Result Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template IndexOf
+// Finds the index of a type in a typelist
+// Invocation (TList is a typelist and T is a type):
+// IndexOf<TList, T>::value
+// returns the position of T in TList, or NullType if T is not found in TList
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, class T> struct IndexOf;
+
+ template <class T>
+ struct IndexOf<NullType, T>
+ {
+ enum { value = -1 };
+ };
+
+ template <class T, class Tail>
+ struct IndexOf<Typelist<T, Tail>, T>
+ {
+ enum { value = 0 };
+ };
+
+ template <class Head, class Tail, class T>
+ struct IndexOf<Typelist<Head, Tail>, T>
+ {
+ private:
+ enum { temp = IndexOf<Tail, T>::value };
+ public:
+ enum { value = (temp == -1 ? -1 : 1 + temp) };
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Append
+// Appends a type or a typelist to another
+// Invocation (TList is a typelist and T is either a type or a typelist):
+// Append<TList, T>::Result
+// returns a typelist that is TList followed by T and NullType-terminated
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, class T> struct Append;
+
+ template <> struct Append<NullType, NullType>
+ {
+ typedef NullType Result;
+ };
+
+ template <class T> struct Append<NullType, T>
+ {
+ typedef Typelist<T,NullType> Result;
+ };
+
+ template <class Head, class Tail>
+ struct Append<NullType, Typelist<Head, Tail> >
+ {
+ typedef Typelist<Head, Tail> Result;
+ };
+
+ template <class Head, class Tail, class T>
+ struct Append<Typelist<Head, Tail>, T>
+ {
+ typedef Typelist<Head,
+ typename Append<Tail, T>::Result>
+ Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Erase
+// Erases the first occurence, if any, of a type in a typelist
+// Invocation (TList is a typelist and T is a type):
+// Erase<TList, T>::Result
+// returns a typelist that is TList without the first occurence of T
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, class T> struct Erase;
+
+ template <class T> // Specialization 1
+ struct Erase<NullType, T>
+ {
+ typedef NullType Result;
+ };
+
+ template <class T, class Tail> // Specialization 2
+ struct Erase<Typelist<T, Tail>, T>
+ {
+ typedef Tail Result;
+ };
+
+ template <class Head, class Tail, class T> // Specialization 3
+ struct Erase<Typelist<Head, Tail>, T>
+ {
+ typedef Typelist<Head,
+ typename Erase<Tail, T>::Result>
+ Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template EraseAll
+// Erases all first occurences, if any, of a type in a typelist
+// Invocation (TList is a typelist and T is a type):
+// EraseAll<TList, T>::Result
+// returns a typelist that is TList without any occurence of T
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, class T> struct EraseAll;
+ template <class T>
+ struct EraseAll<NullType, T>
+ {
+ typedef NullType Result;
+ };
+ template <class T, class Tail>
+ struct EraseAll<Typelist<T, Tail>, T>
+ {
+ // Go all the way down the list removing the type
+ typedef typename EraseAll<Tail, T>::Result Result;
+ };
+ template <class Head, class Tail, class T>
+ struct EraseAll<Typelist<Head, Tail>, T>
+ {
+ // Go all the way down the list removing the type
+ typedef Typelist<Head,
+ typename EraseAll<Tail, T>::Result>
+ Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template NoDuplicates
+// Removes all duplicate types in a typelist
+// Invocation (TList is a typelist):
+// NoDuplicates<TList, T>::Result
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList> struct NoDuplicates;
+
+ template <> struct NoDuplicates<NullType>
+ {
+ typedef NullType Result;
+ };
+
+ template <class Head, class Tail>
+ struct NoDuplicates< Typelist<Head, Tail> >
+ {
+ private:
+ typedef typename NoDuplicates<Tail>::Result L1;
+ typedef typename Erase<L1, Head>::Result L2;
+ public:
+ typedef Typelist<Head, L2> Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Replace
+// Replaces the first occurence of a type in a typelist, with another type
+// Invocation (TList is a typelist, T, U are types):
+// Replace<TList, T, U>::Result
+// returns a typelist in which the first occurence of T is replaced with U
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, class T, class U> struct Replace;
+
+ template <class T, class U>
+ struct Replace<NullType, T, U>
+ {
+ typedef NullType Result;
+ };
+
+ template <class T, class Tail, class U>
+ struct Replace<Typelist<T, Tail>, T, U>
+ {
+ typedef Typelist<U, Tail> Result;
+ };
+
+ template <class Head, class Tail, class T, class U>
+ struct Replace<Typelist<Head, Tail>, T, U>
+ {
+ typedef Typelist<Head,
+ typename Replace<Tail, T, U>::Result>
+ Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template ReplaceAll
+// Replaces all occurences of a type in a typelist, with another type
+// Invocation (TList is a typelist, T, U are types):
+// Replace<TList, T, U>::Result
+// returns a typelist in which all occurences of T is replaced with U
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, class T, class U> struct ReplaceAll;
+
+ template <class T, class U>
+ struct ReplaceAll<NullType, T, U>
+ {
+ typedef NullType Result;
+ };
+
+ template <class T, class Tail, class U>
+ struct ReplaceAll<Typelist<T, Tail>, T, U>
+ {
+ typedef Typelist<U, typename ReplaceAll<Tail, T, U>::Result> Result;
+ };
+
+ template <class Head, class Tail, class T, class U>
+ struct ReplaceAll<Typelist<Head, Tail>, T, U>
+ {
+ typedef Typelist<Head,
+ typename ReplaceAll<Tail, T, U>::Result>
+ Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Reverse
+// Reverses a typelist
+// Invocation (TList is a typelist):
+// Reverse<TList>::Result
+// returns a typelist that is TList reversed
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList> struct Reverse;
+
+ template <>
+ struct Reverse<NullType>
+ {
+ typedef NullType Result;
+ };
+
+ template <class Head, class Tail>
+ struct Reverse< Typelist<Head, Tail> >
+ {
+ typedef typename Append<
+ typename Reverse<Tail>::Result, Head>::Result Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template MostDerived
+// Finds the type in a typelist that is the most derived from a given type
+// Invocation (TList is a typelist, T is a type):
+// MostDerived<TList, T>::Result
+// returns the type in TList that's the most derived from T
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, class T> struct MostDerived;
+
+ template <class T>
+ struct MostDerived<NullType, T>
+ {
+ typedef T Result;
+ };
+
+ template <class Head, class Tail, class T>
+ struct MostDerived<Typelist<Head, Tail>, T>
+ {
+ private:
+ typedef typename MostDerived<Tail, T>::Result Candidate;
+ public:
+ typedef typename Select<
+ SuperSubclass<Candidate,Head>::value,
+ Head, Candidate>::Result Result;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template DerivedToFront
+// Arranges the types in a typelist so that the most derived types appear first
+// Invocation (TList is a typelist):
+// DerivedToFront<TList>::Result
+// returns the reordered TList
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList> struct DerivedToFront;
+
+ template <>
+ struct DerivedToFront<NullType>
+ {
+ typedef NullType Result;
+ };
+
+ template <class Head, class Tail>
+ struct DerivedToFront< Typelist<Head, Tail> >
+ {
+ private:
+ typedef typename MostDerived<Tail, Head>::Result
+ TheMostDerived;
+ typedef typename Replace<Tail,
+ TheMostDerived, Head>::Result Temp;
+ typedef typename DerivedToFront<Temp>::Result L;
+ public:
+ typedef Typelist<TheMostDerived, L> Result;
+ };
+
+ } // namespace TL
+} // namespace Loki
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/TypelistMacros.h b/shared/loki/TypelistMacros.h
new file mode 100644
index 00000000..6c14b348
--- /dev/null
+++ b/shared/loki/TypelistMacros.h
@@ -0,0 +1,353 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Welsey Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_TYPELISTMACROS_INC_
+#define LOKI_TYPELISTMACROS_INC_
+
+// $Id: TypelistMacros.h 749 2006-10-17 19:49:26Z syntheticpp $
+
+
+//#define LOKI_DISABLE_TYPELIST_MACROS
+#ifndef LOKI_DISABLE_TYPELIST_MACROS
+
+////////////////////////////////////////////////////////////////////////////////
+// macros LOKI_TYPELIST_1, LOKI_TYPELIST_2, ... LOKI_TYPELIST_50
+// Each takes a number of arguments equal to its numeric suffix
+// The arguments are type names. LOKI_TYPELIST_NN generates a typelist containing
+// all types passed as arguments, in that order.
+// Example: LOKI_TYPELIST_2(char, int) generates a type containing char and int.
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_TYPELIST_1(T1) ::Loki::Typelist<T1, ::Loki::NullType>
+
+#define LOKI_TYPELIST_2(T1, T2) ::Loki::Typelist<T1, LOKI_TYPELIST_1(T2) >
+
+#define LOKI_TYPELIST_3(T1, T2, T3) ::Loki::Typelist<T1, LOKI_TYPELIST_2(T2, T3) >
+
+#define LOKI_TYPELIST_4(T1, T2, T3, T4) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_3(T2, T3, T4) >
+
+#define LOKI_TYPELIST_5(T1, T2, T3, T4, T5) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_4(T2, T3, T4, T5) >
+
+#define LOKI_TYPELIST_6(T1, T2, T3, T4, T5, T6) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_5(T2, T3, T4, T5, T6) >
+
+#define LOKI_TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_6(T2, T3, T4, T5, T6, T7) >
+
+#define LOKI_TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_7(T2, T3, T4, T5, T6, T7, T8) >
+
+#define LOKI_TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_8(T2, T3, T4, T5, T6, T7, T8, T9) >
+
+#define LOKI_TYPELIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_9(T2, T3, T4, T5, T6, T7, T8, T9, T10) >
+
+#define LOKI_TYPELIST_11(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_10(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) >
+
+#define LOKI_TYPELIST_12(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_11(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12) >
+
+#define LOKI_TYPELIST_13(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_12(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13) >
+
+#define LOKI_TYPELIST_14(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_13(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14) >
+
+#define LOKI_TYPELIST_15(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_14(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15) >
+
+#define LOKI_TYPELIST_16(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_15(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16) >
+
+#define LOKI_TYPELIST_17(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_16(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17) >
+
+#define LOKI_TYPELIST_18(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_17(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18) >
+
+#define LOKI_TYPELIST_19(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_18(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19) >
+
+#define LOKI_TYPELIST_20(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_19(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) >
+
+#define LOKI_TYPELIST_21(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_20(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) >
+
+#define LOKI_TYPELIST_22(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_21(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) >
+
+#define LOKI_TYPELIST_23(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_22(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) >
+
+#define LOKI_TYPELIST_24(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_23(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) >
+
+#define LOKI_TYPELIST_25(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_24(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25) >
+
+#define LOKI_TYPELIST_26(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_25(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26) >
+
+#define LOKI_TYPELIST_27(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_26(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27) >
+
+#define LOKI_TYPELIST_28(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_27(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28) >
+
+#define LOKI_TYPELIST_29(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_28(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29) >
+
+#define LOKI_TYPELIST_30(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_29(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) >
+
+#define LOKI_TYPELIST_31(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_30(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) >
+
+#define LOKI_TYPELIST_32(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_31(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) >
+
+#define LOKI_TYPELIST_33(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_32(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) >
+
+#define LOKI_TYPELIST_34(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_33(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) >
+
+#define LOKI_TYPELIST_35(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_34(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35) >
+
+#define LOKI_TYPELIST_36(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_35(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36) >
+
+#define LOKI_TYPELIST_37(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_36(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37) >
+
+#define LOKI_TYPELIST_38(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_37(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38) >
+
+#define LOKI_TYPELIST_39(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_38(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39) >
+
+#define LOKI_TYPELIST_40(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_39(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) >
+
+#define LOKI_TYPELIST_41(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_40(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) >
+
+#define LOKI_TYPELIST_42(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_41(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) >
+
+#define LOKI_TYPELIST_43(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_42(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) >
+
+#define LOKI_TYPELIST_44(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_43(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) >
+
+#define LOKI_TYPELIST_45(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_44(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45) >
+
+#define LOKI_TYPELIST_46(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_45(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46) >
+
+#define LOKI_TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46, T47) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_46(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46, T47) >
+
+#define LOKI_TYPELIST_48(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46, T47, T48) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_47(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46, T47, T48) >
+
+#define LOKI_TYPELIST_49(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46, T47, T48, T49) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_48(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46, T47, T48, T49) >
+
+#define LOKI_TYPELIST_50(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) \
+ ::Loki::Typelist<T1, LOKI_TYPELIST_49(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
+ T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \
+ T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \
+ T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \
+ T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) >
+
+#endif //LOKI_DISABLE_TYPELIST_MACROS
+
+#endif // end file guardian
+
diff --git a/shared/loki/Visitor.h b/shared/loki/Visitor.h
new file mode 100644
index 00000000..4425a9fa
--- /dev/null
+++ b/shared/loki/Visitor.h
@@ -0,0 +1,355 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_VISITOR_INC_
+#define LOKI_VISITOR_INC_
+
+// $Id: Visitor.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+/// \defgroup VisitorGroup Visitor
+
+#include "Typelist.h"
+#include "HierarchyGenerators.h"
+
+namespace Loki
+{
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class BaseVisitor
+///
+/// \ingroup VisitorGroup
+/// The base class of any Acyclic Visitor
+////////////////////////////////////////////////////////////////////////////////
+
+ class BaseVisitor
+ {
+ public:
+ virtual ~BaseVisitor() {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class Visitor
+///
+/// \ingroup VisitorGroup
+/// The building block of Acyclic Visitor
+///
+/// \par Usage
+///
+/// Defining the visitable class:
+///
+/// \code
+/// class RasterBitmap : public BaseVisitable<>
+/// {
+/// public:
+/// LOKI_DEFINE_VISITABLE()
+/// };
+/// \endcode
+///
+/// Way 1 to define a visitor:
+/// \code
+/// class SomeVisitor :
+/// public BaseVisitor // required
+/// public Visitor<RasterBitmap>,
+/// public Visitor<Paragraph>
+/// {
+/// public:
+/// void Visit(RasterBitmap&); // visit a RasterBitmap
+/// void Visit(Paragraph &); // visit a Paragraph
+/// };
+/// \endcode
+///
+/// Way 2 to define the visitor:
+/// \code
+/// class SomeVisitor :
+/// public BaseVisitor // required
+/// public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)>
+/// {
+/// public:
+/// void Visit(RasterBitmap&); // visit a RasterBitmap
+/// void Visit(Paragraph &); // visit a Paragraph
+/// };
+/// \endcode
+///
+/// Way 3 to define the visitor:
+/// \code
+/// class SomeVisitor :
+/// public BaseVisitor // required
+/// public Visitor<Seq<RasterBitmap, Paragraph>::Type>
+/// {
+/// public:
+/// void Visit(RasterBitmap&); // visit a RasterBitmap
+/// void Visit(Paragraph &); // visit a Paragraph
+/// };
+/// \endcode
+///
+/// \par Using const visit functions:
+///
+/// Defining the visitable class (true for const):
+///
+/// \code
+/// class RasterBitmap : public BaseVisitable<void, DefaultCatchAll, true>
+/// {
+/// public:
+/// LOKI_DEFINE_CONST_VISITABLE()
+/// };
+/// \endcode
+///
+/// Defining the visitor which only calls const member functions:
+/// \code
+/// class SomeVisitor :
+/// public BaseVisitor // required
+/// public Visitor<RasterBitmap, void, true>,
+/// {
+/// public:
+/// void Visit(const RasterBitmap&); // visit a RasterBitmap by a const member function
+/// };
+/// \endcode
+///
+/// \par Example:
+///
+/// test/Visitor/main.cpp
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T, typename R = void, bool ConstVisit = false>
+ class Visitor;
+
+ template <class T, typename R>
+ class Visitor<T, R, false>
+ {
+ public:
+ typedef R ReturnType;
+ typedef T ParamType;
+ virtual ~Visitor() {}
+ virtual ReturnType Visit(ParamType&) = 0;
+ };
+
+ template <class T, typename R>
+ class Visitor<T, R, true>
+ {
+ public:
+ typedef R ReturnType;
+ typedef const T ParamType;
+ virtual ~Visitor() {}
+ virtual ReturnType Visit(ParamType&) = 0;
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template Visitor (specialization)
+// This specialization is not present in the book. It makes it easier to define
+// Visitors for multiple types in a shot by using a typelist. Example:
+//
+// class SomeVisitor :
+// public BaseVisitor // required
+// public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)>
+// {
+// public:
+// void Visit(RasterBitmap&); // visit a RasterBitmap
+// void Visit(Paragraph &); // visit a Paragraph
+// };
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class Head, class Tail, typename R>
+ class Visitor<Typelist<Head, Tail>, R, false>
+ : public Visitor<Head, R, false>, public Visitor<Tail, R, false>
+ {
+ public:
+ typedef R ReturnType;
+ // using Visitor<Head, R>::Visit;
+ // using Visitor<Tail, R>::Visit;
+ };
+
+ template <class Head, typename R>
+ class Visitor<Typelist<Head, NullType>, R, false> : public Visitor<Head, R, false>
+ {
+ public:
+ typedef R ReturnType;
+ using Visitor<Head, R, false>::Visit;
+ };
+
+ template <class Head, class Tail, typename R>
+ class Visitor<Typelist<Head, Tail>, R, true>
+ : public Visitor<Head, R, true>, public Visitor<Tail, R, true>
+ {
+ public:
+ typedef R ReturnType;
+ // using Visitor<Head, R>::Visit;
+ // using Visitor<Tail, R>::Visit;
+ };
+
+ template <class Head, typename R>
+ class Visitor<Typelist<Head, NullType>, R, true> : public Visitor<Head, R, true>
+ {
+ public:
+ typedef R ReturnType;
+ using Visitor<Head, R, true>::Visit;
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class template BaseVisitorImpl
+// Implements non-strict visitation (you can implement only part of the Visit
+// functions)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, typename R = void> class BaseVisitorImpl;
+
+ template <class Head, class Tail, typename R>
+ class BaseVisitorImpl<Typelist<Head, Tail>, R>
+ : public Visitor<Head, R>
+ , public BaseVisitorImpl<Tail, R>
+ {
+ public:
+ // using BaseVisitorImpl<Tail, R>::Visit;
+
+ virtual R Visit(Head&)
+ { return R(); }
+ };
+
+ template <class Head, typename R>
+ class BaseVisitorImpl<Typelist<Head, NullType>, R>
+ : public Visitor<Head, R>
+ {
+ public:
+ virtual R Visit(Head&)
+ { return R(); }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template BaseVisitable
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename R, typename Visited>
+struct DefaultCatchAll
+{
+ static R OnUnknownVisitor(Visited&, BaseVisitor&)
+ { return R(); }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// class template BaseVisitable
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename R = void,
+ template <typename, class> class CatchAll = DefaultCatchAll,
+ bool ConstVisitable = false
+ >
+ class BaseVisitable;
+
+ template<typename R,template <typename, class> class CatchAll>
+ class BaseVisitable<R, CatchAll, false>
+ {
+ public:
+ typedef R ReturnType;
+ virtual ~BaseVisitable() {}
+ virtual ReturnType Accept(BaseVisitor&) = 0;
+
+ protected: // give access only to the hierarchy
+ template <class T>
+ static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
+ {
+ // Apply the Acyclic Visitor
+ if (Visitor<T,R>* p = dynamic_cast<Visitor<T,R>*>(&guest))
+ {
+ return p->Visit(visited);
+ }
+ return CatchAll<R, T>::OnUnknownVisitor(visited, guest);
+ }
+ };
+
+ template<typename R,template <typename, class> class CatchAll>
+ class BaseVisitable<R, CatchAll, true>
+ {
+ public:
+ typedef R ReturnType;
+ virtual ~BaseVisitable() {}
+ virtual ReturnType Accept(BaseVisitor&) const = 0;
+
+ protected: // give access only to the hierarchy
+ template <class T>
+ static ReturnType AcceptImpl(const T& visited, BaseVisitor& guest)
+ {
+ // Apply the Acyclic Visitor
+ if (Visitor<T,R,true>* p = dynamic_cast<Visitor<T,R,true>*>(&guest))
+ {
+ return p->Visit(visited);
+ }
+ return CatchAll<R, T>::OnUnknownVisitor(const_cast<T&>(visited), guest);
+ }
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \def LOKI_DEFINE_VISITABLE()
+/// \ingroup VisitorGroup
+/// Put it in every class that you want to make visitable
+/// (in addition to deriving it from BaseVisitable<R>)
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_DEFINE_VISITABLE() \
+ virtual ReturnType Accept(::Loki::BaseVisitor& guest) \
+ { return AcceptImpl(*this, guest); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// \def LOKI_DEFINE_CONST_VISITABLE()
+/// \ingroup VisitorGroup
+/// Put it in every class that you want to make visitable by const member
+/// functions (in addition to deriving it from BaseVisitable<R>)
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_DEFINE_CONST_VISITABLE() \
+ virtual ReturnType Accept(::Loki::BaseVisitor& guest) const \
+ { return AcceptImpl(*this, guest); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class CyclicVisitor
+///
+/// \ingroup VisitorGroup
+/// Put it in every class that you want to make visitable (in addition to
+/// deriving it from BaseVisitable<R>
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, class TList>
+ class CyclicVisitor : public Visitor<TList, R>
+ {
+ public:
+ typedef R ReturnType;
+ // using Visitor<TList, R>::Visit;
+
+ template <class Visited>
+ ReturnType GenericVisit(Visited& host)
+ {
+ Visitor<Visited, ReturnType>& subObj = *this;
+ return subObj.Visit(host);
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \def LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor)
+/// \ingroup VisitorGroup
+/// Put it in every class that you want to make visitable by a cyclic visitor
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor) \
+ virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \
+ { return guest.GenericVisit(*this); }
+
+} // namespace Loki
+
+
+
+#endif // end file guardian
+
diff --git a/shared/loki/readme.txt b/shared/loki/readme.txt
new file mode 100644
index 00000000..a35cf387
--- /dev/null
+++ b/shared/loki/readme.txt
@@ -0,0 +1,12 @@
+// $Id: readme.txt 753 2006-10-17 19:54:22Z syntheticpp $
+
+The Golden Code
+KEEPEN DER DAMDDEN FUGGERMUTTENS OTTEN DIS CODDEN FIL
+
+A compliant C++ compiler will compile all of this code as is.
+See the respective vendor directories for code that actually compiles & runs.
+
+Note: Right now, this code contains CodeWarrior & gcc modifications,
+which may be removed at a future point in time
+(by moving them to a vendor specific implementation).
+MKH \ No newline at end of file
diff --git a/shared/loki/static_check.h b/shared/loki/static_check.h
new file mode 100644
index 00000000..51ce389e
--- /dev/null
+++ b/shared/loki/static_check.h
@@ -0,0 +1,45 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_STATIC_CHECK_INC_
+#define LOKI_STATIC_CHECK_INC_
+
+// $Id: static_check.h 752 2006-10-17 19:52:18Z syntheticpp $
+
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// Helper structure for the STATIC_CHECK macro
+////////////////////////////////////////////////////////////////////////////////
+
+ template<int> struct CompileTimeError;
+ template<> struct CompileTimeError<true> {};
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// macro STATIC_CHECK
+// Invocation: STATIC_CHECK(expr, id)
+// where:
+// expr is a compile-time integral or pointer expression
+// id is a C++ identifier that does not need to be defined
+// If expr is zero, id will appear in a compile-time error message.
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_STATIC_CHECK(expr, msg) \
+ { Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
+
+
+#endif // end file guardian
+
diff --git a/shared/shadow.cpp b/shared/shadow.cpp
index 02a6a522..da7cfd99 100644
--- a/shared/shadow.cpp
+++ b/shared/shadow.cpp
@@ -30,9 +30,9 @@ public:
private:
ShadowlDllHandler() :
- createShadowCopy(NULL),
- releaseShadowCopy(NULL),
- hShadow(NULL)
+ createShadowCopy(NULL),
+ releaseShadowCopy(NULL),
+ hShadow(NULL)
{
//get a handle to the DLL module containing the required functionality
hShadow = ::LoadLibrary(L"Shadow.dll");
@@ -53,7 +53,7 @@ private:
ShadowCopy::ShadowCopy() :
- backupHandle(NULL) {}
+ backupHandle(NULL) {}
ShadowCopy::~ShadowCopy()
diff --git a/shared/shadow.h b/shared/shadow.h
index 15fd4d9d..8affdebf 100644
--- a/shared/shadow.h
+++ b/shared/shadow.h
@@ -11,21 +11,21 @@ header should be used in the windows build only!
namespace FreeFileSync
{
- class ShadowCopy //buffer access to Windows Volume Shadow Copy Service
- {
- public:
- ShadowCopy();
- ~ShadowCopy();
+class ShadowCopy //buffer access to Windows Volume Shadow Copy Service
+{
+public:
+ ShadowCopy();
+ ~ShadowCopy();
- Zstring makeShadowCopy(const Zstring& inputFile); //throw(FileError); returns filename on shadow copy
+ Zstring makeShadowCopy(const Zstring& inputFile); //throw(FileError); returns filename on shadow copy
- private:
- bool isOkay();
+private:
+ bool isOkay();
- Zstring realVolumeLast; //buffer last volume name
- Zstring shadowVolumeLast; //buffer last created shadow volume
- void* backupHandle;
- };
+ Zstring realVolumeLast; //buffer last volume name
+ Zstring shadowVolumeLast; //buffer last created shadow volume
+ void* backupHandle;
+};
}
#endif // SHADOW_H_INCLUDED
diff --git a/shared/standardPaths.cpp b/shared/standardPaths.cpp
index 54774673..3d5cfdb5 100644
--- a/shared/standardPaths.cpp
+++ b/shared/standardPaths.cpp
@@ -2,20 +2,23 @@
#include <wx/stdpaths.h>
#include <wx/filename.h>
#include "systemConstants.h"
+#include "stringConv.h"
+
+using namespace FreeFileSync;
wxString assembleFileForUserData(const wxString fileName)
{
- static const bool isPortableVersion = !wxFileExists(FreeFileSync::getInstallationDir() + globalFunctions::FILE_NAME_SEPARATOR + wxT("uninstall.exe")); //this check is a bit lame...
+ static const bool isPortableVersion = !wxFileExists(FreeFileSync::getInstallationDir() + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + wxT("uninstall.exe")); //this check is a bit lame...
if (isPortableVersion) //use current working directory
- return wxString(wxT(".")) + globalFunctions::FILE_NAME_SEPARATOR + fileName;
+ return wxString(wxT(".")) + zToWx(globalFunctions::FILE_NAME_SEPARATOR) + fileName;
else //usen OS' standard paths
{
wxString userDirectory = wxStandardPathsBase::Get().GetUserDataDir();
- if (!userDirectory.EndsWith(wxString(globalFunctions::FILE_NAME_SEPARATOR)))
- userDirectory += globalFunctions::FILE_NAME_SEPARATOR;
+ if (!userDirectory.EndsWith(zToWx(globalFunctions::FILE_NAME_SEPARATOR)))
+ userDirectory += zToWx(globalFunctions::FILE_NAME_SEPARATOR);
if (!wxDirExists(userDirectory))
::wxMkdir(userDirectory); //only top directory needs to be created: no recursion necessary
diff --git a/shared/standardPaths.h b/shared/standardPaths.h
index 64811246..34f6ab48 100644
--- a/shared/standardPaths.h
+++ b/shared/standardPaths.h
@@ -9,11 +9,11 @@ namespace FreeFileSync
//------------------------------------------------------------------------------
//global functions
//------------------------------------------------------------------------------
- const wxString& getGlobalConfigFile();
- const wxString& getDefaultLogDirectory();
- const wxString& getLastErrorTxtFile();
- const wxString& getInstallationDir(); //FreeFileSync installation directory without path separator
- const wxString& getConfigDir();
+const wxString& getGlobalConfigFile();
+const wxString& getDefaultLogDirectory();
+const wxString& getLastErrorTxtFile();
+const wxString& getInstallationDir(); //FreeFileSync installation directory without path separator
+const wxString& getConfigDir();
//------------------------------------------------------------------------------
}
diff --git a/shared/stringConv.h b/shared/stringConv.h
new file mode 100644
index 00000000..f4048aab
--- /dev/null
+++ b/shared/stringConv.h
@@ -0,0 +1,104 @@
+#ifndef STRINGCONV_H_INCLUDED
+#define STRINGCONV_H_INCLUDED
+
+#include <wx/string.h>
+#include "zstring.h"
+
+namespace FreeFileSync
+{
+//conversion from Zstring to wxString
+wxString zToWx(const Zstring& str);
+wxString zToWx(const DefaultChar* str);
+wxString zToWx(DefaultChar ch);
+//conversion from wxString to Zstring
+Zstring wxToZ(const wxString& str);
+Zstring wxToZ(const wxChar* str);
+Zstring wxToZ(wxChar ch);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//---------------Inline Implementation---------------------------------------------------
+inline
+wxString zToWx(const Zstring& str)
+{
+#ifdef ZSTRING_CHAR
+ return wxString::FromUTF8(str.c_str(), str.length());
+#elif defined ZSTRING_WIDE_CHAR
+ return wxString(str.c_str(), str.length());
+#endif
+}
+
+
+inline
+wxString zToWx(const DefaultChar* str)
+{
+#ifdef ZSTRING_CHAR
+ return wxString::FromUTF8(str);
+#elif defined ZSTRING_WIDE_CHAR
+ return str;
+#endif
+}
+
+
+inline
+wxString zToWx(DefaultChar ch)
+{
+ return zToWx(Zstring() + ch);
+}
+
+//-----------------------------------------------------------------
+inline
+Zstring wxToZ(const wxString& str)
+{
+#ifdef ZSTRING_CHAR
+ return Zstring(str.ToUTF8());
+#elif defined ZSTRING_WIDE_CHAR
+ return Zstring(str.c_str(), str.length());
+#endif
+}
+
+
+inline
+Zstring wxToZ(const wxChar* str)
+{
+#ifdef ZSTRING_CHAR
+ return Zstring(wxString(str).ToUTF8());
+#elif defined ZSTRING_WIDE_CHAR
+ return str;
+#endif
+}
+
+
+inline
+Zstring wxToZ(wxChar ch)
+{
+ return wxToZ(wxString(ch));
+}
+}
+
+#endif // STRINGCONV_H_INCLUDED
diff --git a/shared/systemConstants.h b/shared/systemConstants.h
index 84c1ae85..bae23d5a 100644
--- a/shared/systemConstants.h
+++ b/shared/systemConstants.h
@@ -2,7 +2,7 @@
#define SYSTEMCONSTANTS_H_INCLUDED
#include "zstring.h"
-
+#include <wx/string.h>
namespace globalFunctions
{
@@ -10,11 +10,11 @@ namespace globalFunctions
// GLOBALS
//------------------------------------------------
#ifdef FFS_WIN
- const DefaultChar FILE_NAME_SEPARATOR = '\\';
- static const DefaultChar* const LINE_BREAK = L"\r\n"; //internal linkage
+const DefaultChar FILE_NAME_SEPARATOR = '\\';
+static const wxChar* const LINE_BREAK = wxT("\r\n"); //internal linkage
#elif defined FFS_LINUX
- const DefaultChar FILE_NAME_SEPARATOR = '/';
- static const DefaultChar* const LINE_BREAK = "\n";
+const DefaultChar FILE_NAME_SEPARATOR = '/';
+static const wxChar* const LINE_BREAK = wxT("\n");
#endif
}
diff --git a/shared/systemFunctions.cpp b/shared/systemFunctions.cpp
index 4fd17fc1..3d6915cd 100644
--- a/shared/systemFunctions.cpp
+++ b/shared/systemFunctions.cpp
@@ -11,27 +11,29 @@
#ifdef FFS_WIN
-wxString FreeFileSync::getLastErrorFormatted(const unsigned long lastError) //try to get additional Windows error information
+wxString FreeFileSync::getLastErrorFormatted(unsigned long lastError) //try to get additional Windows error information
{
//determine error code if none was specified
- const unsigned long lastErrorCode = lastError == 0 ? ::GetLastError() : lastError;
+ if (lastError == 0)
+ lastError = ::GetLastError();
- wxString output = wxString(wxT("Windows Error Code ")) + wxString::Format(wxT("%u"), lastErrorCode);
+ wxString output = wxString(wxT("Windows Error Code ")) + wxString::Format(wxT("%u"), lastError);
WCHAR buffer[1001];
- if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0, lastErrorCode, 0, buffer, 1001, NULL) != 0)
+ if (::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0, lastError, 0, buffer, 1001, NULL) != 0)
output += wxString(wxT(": ")) + buffer;
return output;
}
#elif defined FFS_LINUX
-wxString FreeFileSync::getLastErrorFormatted(const int lastError) //try to get additional Linux error information
+wxString FreeFileSync::getLastErrorFormatted(int lastError) //try to get additional Linux error information
{
//determine error code if none was specified
- const int lastErrorCode = lastError == 0 ? errno : lastError;
+ if (lastError == 0)
+ lastError = errno; //don't use :: errno is a macro!
- wxString output = wxString(wxT("Linux Error Code ")) + wxString::Format(wxT("%i"), lastErrorCode);
- output += wxString(wxT(": ")) + ::strerror(lastErrorCode);
+ wxString output = wxString(wxT("Linux Error Code ")) + wxString::Format(wxT("%i"), lastError);
+ output += wxString(wxT(": ")) + wxString::FromUTF8(::strerror(lastError));
return output;
}
#endif
diff --git a/shared/systemFunctions.h b/shared/systemFunctions.h
index b449d8d2..bfeacdd4 100644
--- a/shared/systemFunctions.h
+++ b/shared/systemFunctions.h
@@ -8,9 +8,9 @@ namespace FreeFileSync
{
#ifdef FFS_WIN
- wxString getLastErrorFormatted(const unsigned long lastError = 0); //try to get additional Windows error information
+wxString getLastErrorFormatted(unsigned long lastError = 0); //try to get additional Windows error information
#elif defined FFS_LINUX
- wxString getLastErrorFormatted(const int lastError = 0); //try to get additional Linux error information
+wxString getLastErrorFormatted(int lastError = 0); //try to get additional Linux error information
#endif
}
diff --git a/shared/tinyxml/tinyxml.cpp b/shared/tinyxml/tinyxml.cpp
index aa13deec..033d13be 100644
--- a/shared/tinyxml/tinyxml.cpp
+++ b/shared/tinyxml/tinyxml.cpp
@@ -504,7 +504,7 @@ const TiXmlDocument* TiXmlNode::GetDocument() const
TiXmlElement::TiXmlElement (const char * _value)
- : TiXmlNode( TiXmlNode::ELEMENT )
+ : TiXmlNode( TiXmlNode::ELEMENT )
{
firstChild = lastChild = 0;
value = _value;
@@ -513,7 +513,7 @@ TiXmlElement::TiXmlElement (const char * _value)
#ifdef TIXML_USE_STL
TiXmlElement::TiXmlElement( const std::string& _value )
- : TiXmlNode( TiXmlNode::ELEMENT )
+ : TiXmlNode( TiXmlNode::ELEMENT )
{
firstChild = lastChild = 0;
value = _value;
@@ -522,7 +522,7 @@ TiXmlElement::TiXmlElement( const std::string& _value )
TiXmlElement::TiXmlElement( const TiXmlElement& copy)
- : TiXmlNode( TiXmlNode::ELEMENT )
+ : TiXmlNode( TiXmlNode::ELEMENT )
{
firstChild = lastChild = 0;
copy.CopyTo( this );
@@ -1418,7 +1418,7 @@ TiXmlNode* TiXmlText::Clone() const
TiXmlDeclaration::TiXmlDeclaration( const char * _version,
const char * _encoding,
const char * _standalone )
- : TiXmlNode( TiXmlNode::DECLARATION )
+ : TiXmlNode( TiXmlNode::DECLARATION )
{
version = _version;
encoding = _encoding;
@@ -1430,7 +1430,7 @@ TiXmlDeclaration::TiXmlDeclaration( const char * _version,
TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
const std::string& _encoding,
const std::string& _standalone )
- : TiXmlNode( TiXmlNode::DECLARATION )
+ : TiXmlNode( TiXmlNode::DECLARATION )
{
version = _version;
encoding = _encoding;
@@ -1440,7 +1440,7 @@ TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
- : TiXmlNode( TiXmlNode::DECLARATION )
+ : TiXmlNode( TiXmlNode::DECLARATION )
{
copy.CopyTo( this );
}
diff --git a/shared/tinyxml/tinyxmlparser.cpp b/shared/tinyxml/tinyxmlparser.cpp
index a601016a..503becde 100644
--- a/shared/tinyxml/tinyxmlparser.cpp
+++ b/shared/tinyxml/tinyxmlparser.cpp
@@ -433,11 +433,11 @@ const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncodi
{
const char* start = p;
while ( p && *p
- && ( IsAlphaNum( (unsigned char ) *p, encoding )
- || *p == '_'
- || *p == '-'
- || *p == '.'
- || *p == ':' ) )
+ && ( IsAlphaNum( (unsigned char ) *p, encoding )
+ || *p == '_'
+ || *p == '-'
+ || *p == '.'
+ || *p == ':' ) )
{
//(*name) += *p; // expensive
++p;
@@ -588,11 +588,11 @@ bool TiXmlBase::StringEqual( const char* p,
}
const char* TiXmlBase::ReadText( const char* p,
- TIXML_STRING * text,
- bool trimWhiteSpace,
- const char* endTag,
- bool caseInsensitive,
- TiXmlEncoding encoding )
+ TIXML_STRING * text,
+ bool trimWhiteSpace,
+ const char* endTag,
+ bool caseInsensitive,
+ TiXmlEncoding encoding )
{
*text = "";
if ( !trimWhiteSpace // certain tags always keep whitespace
diff --git a/shared/toggleButton.h b/shared/toggleButton.h
index b7475e0c..1110ad5d 100644
--- a/shared/toggleButton.h
+++ b/shared/toggleButton.h
@@ -14,8 +14,8 @@ public:
long style = 0,
const wxValidator& validator = wxDefaultValidator,
const wxString& name = wxButtonNameStr) :
- wxBitmapButton(parent, id, bitmap, pos, size, style, validator, name),
- active(false) {}
+ wxBitmapButton(parent, id, bitmap, pos, size, style, validator, name),
+ active(false) {}
void init(const wxBitmap& activeBmp,
const wxString& activeTooltip,
diff --git a/shared/xmlBase.cpp b/shared/xmlBase.cpp
index ba96b663..c098f94a 100644
--- a/shared/xmlBase.cpp
+++ b/shared/xmlBase.cpp
@@ -43,7 +43,8 @@ xmlAccess::XmlType xmlAccess::getXmlType(const wxString& filename)
return XML_OTHER;
}
catch (const std::exception&)
- { //unfortunately TiXml isn't very smart and tries to allocate space for the complete file: length_error exception is thrown for large files!
+ {
+ //unfortunately TiXml isn't very smart and tries to allocate space for the complete file: length_error exception is thrown for large files!
return XML_OTHER;
}
diff --git a/shared/xmlBase.h b/shared/xmlBase.h
index ed838843..3a01c515 100644
--- a/shared/xmlBase.h
+++ b/shared/xmlBase.h
@@ -10,108 +10,108 @@
namespace xmlAccess
{
- enum XmlType
- {
- XML_GUI_CONFIG,
- XML_BATCH_CONFIG,
- XML_GLOBAL_SETTINGS,
- XML_REAL_CONFIG,
- XML_OTHER
- };
+enum XmlType
+{
+ XML_GUI_CONFIG,
+ XML_BATCH_CONFIG,
+ XML_GLOBAL_SETTINGS,
+ XML_REAL_CONFIG,
+ XML_OTHER
+};
- XmlType getXmlType(const wxString& filename);
+XmlType getXmlType(const wxString& filename);
- bool loadXmlDocument(const wxString& fileName, const XmlType type, TiXmlDocument& document);
- void getDefaultXmlDocument(const XmlType type, TiXmlDocument& document);
- bool saveXmlDocument(const wxString& fileName, const TiXmlDocument& document);
+bool loadXmlDocument(const wxString& fileName, const XmlType type, TiXmlDocument& document);
+void getDefaultXmlDocument(const XmlType type, TiXmlDocument& document);
+bool saveXmlDocument(const wxString& fileName, const TiXmlDocument& document);
//------------------------------------------------------------------------------------------
- //small helper functions
- bool readXmlElement(const std::string& name, const TiXmlElement* parent, std::string& output);
- bool readXmlElement(const std::string& name, const TiXmlElement* parent, wxString& output);
- bool readXmlElement(const std::string& name, const TiXmlElement* parent, int& output);
- bool readXmlElement(const std::string& name, const TiXmlElement* parent, unsigned int& output);
- bool readXmlElement(const std::string& name, const TiXmlElement* parent, long& output);
- bool readXmlElement(const std::string& name, const TiXmlElement* parent, bool& output);
- bool readXmlElement(const std::string& name, const TiXmlElement* parent, std::vector<wxString>& output);
-
- bool readXmlAttribute(const std::string& name, const TiXmlElement* node, std::string& output);
- bool readXmlAttribute(const std::string& name, const TiXmlElement* node, wxString& output);
- bool readXmlAttribute(const std::string& name, const TiXmlElement* node, int& output);
- bool readXmlAttribute(const std::string& name, const TiXmlElement* node, unsigned int& output);
- bool readXmlAttribute(const std::string& name, const TiXmlElement* node, bool& output);
-
- void addXmlElement(const std::string& name, const std::string& value, TiXmlElement* parent);
- void addXmlElement(const std::string& name, const wxString& value, TiXmlElement* parent);
- void addXmlElement(const std::string& name, const int value, TiXmlElement* parent);
- void addXmlElement(const std::string& name, const unsigned int value, TiXmlElement* parent);
- void addXmlElement(const std::string& name, const long value, TiXmlElement* parent);
- void addXmlElement(const std::string& name, const bool value, TiXmlElement* parent);
- void addXmlElement(const std::string& name, const std::vector<wxString>& value, TiXmlElement* parent);
-
- void addXmlAttribute(const std::string& name, const std::string& value, TiXmlElement* node);
- void addXmlAttribute(const std::string& name, const wxString& value, TiXmlElement* node);
- void addXmlAttribute(const std::string& name, const int value, TiXmlElement* node);
- void addXmlAttribute(const std::string& name, const unsigned int value, TiXmlElement* node);
- void addXmlAttribute(const std::string& name, const bool value, TiXmlElement* node);
-
-
-
- class XmlParser
+//small helper functions
+bool readXmlElement(const std::string& name, const TiXmlElement* parent, std::string& output);
+bool readXmlElement(const std::string& name, const TiXmlElement* parent, wxString& output);
+bool readXmlElement(const std::string& name, const TiXmlElement* parent, int& output);
+bool readXmlElement(const std::string& name, const TiXmlElement* parent, unsigned int& output);
+bool readXmlElement(const std::string& name, const TiXmlElement* parent, long& output);
+bool readXmlElement(const std::string& name, const TiXmlElement* parent, bool& output);
+bool readXmlElement(const std::string& name, const TiXmlElement* parent, std::vector<wxString>& output);
+
+bool readXmlAttribute(const std::string& name, const TiXmlElement* node, std::string& output);
+bool readXmlAttribute(const std::string& name, const TiXmlElement* node, wxString& output);
+bool readXmlAttribute(const std::string& name, const TiXmlElement* node, int& output);
+bool readXmlAttribute(const std::string& name, const TiXmlElement* node, unsigned int& output);
+bool readXmlAttribute(const std::string& name, const TiXmlElement* node, bool& output);
+
+void addXmlElement(const std::string& name, const std::string& value, TiXmlElement* parent);
+void addXmlElement(const std::string& name, const wxString& value, TiXmlElement* parent);
+void addXmlElement(const std::string& name, const int value, TiXmlElement* parent);
+void addXmlElement(const std::string& name, const unsigned int value, TiXmlElement* parent);
+void addXmlElement(const std::string& name, const long value, TiXmlElement* parent);
+void addXmlElement(const std::string& name, const bool value, TiXmlElement* parent);
+void addXmlElement(const std::string& name, const std::vector<wxString>& value, TiXmlElement* parent);
+
+void addXmlAttribute(const std::string& name, const std::string& value, TiXmlElement* node);
+void addXmlAttribute(const std::string& name, const wxString& value, TiXmlElement* node);
+void addXmlAttribute(const std::string& name, const int value, TiXmlElement* node);
+void addXmlAttribute(const std::string& name, const unsigned int value, TiXmlElement* node);
+void addXmlAttribute(const std::string& name, const bool value, TiXmlElement* node);
+
+
+
+class XmlParser
+{
+public:
+ XmlParser(const TiXmlElement* rootElement) : root(rootElement) {}
+
+ void logError(const std::string& nodeName);
+ bool errorsOccured() const;
+ const wxString getErrorMessageFormatted() const;
+
+protected:
+ //another level of indirection: if errors occur during xml parsing they are logged
+ template <class T>
+ void readXmlElementLogging(const std::string& name, const TiXmlElement* parent, T& output)
{
- public:
- XmlParser(const TiXmlElement* rootElement) : root(rootElement) {}
-
- void logError(const std::string& nodeName);
- bool errorsOccured() const;
- const wxString getErrorMessageFormatted() const;
-
- protected:
- //another level of indirection: if errors occur during xml parsing they are logged
- template <class T>
- void readXmlElementLogging(const std::string& name, const TiXmlElement* parent, T& output)
- {
- if (!readXmlElement(name, parent, output))
- logError(name);
- }
-
- template <class T>
- void readXmlAttributeLogging(const std::string& name, const TiXmlElement* node, T& output)
- {
- if (!readXmlAttribute(name, node, output))
- logError(name);
- }
-
- const TiXmlElement* const root;
- std::vector<wxString> failedNodes;
- };
+ if (!readXmlElement(name, parent, output))
+ logError(name);
+ }
+ template <class T>
+ void readXmlAttributeLogging(const std::string& name, const TiXmlElement* node, T& output)
+ {
+ if (!readXmlAttribute(name, node, output))
+ logError(name);
+ }
- class XmlError //Exception class
+ const TiXmlElement* const root;
+ std::vector<wxString> failedNodes;
+};
+
+
+class XmlError //Exception class
+{
+public:
+ enum Severity
{
- public:
- enum Severity
- {
- WARNING = 77,
- FATAL
- };
-
- XmlError(const wxString& message, Severity sev = FATAL) : errorMessage(message), m_severity(sev) {}
-
- const wxString& show() const
- {
- return errorMessage;
- }
- Severity getSeverity() const
- {
- return m_severity;
- }
- private:
- const wxString errorMessage;
- const Severity m_severity;
+ WARNING = 77,
+ FATAL
};
+
+ XmlError(const wxString& message, Severity sev = FATAL) : errorMessage(message), m_severity(sev) {}
+
+ const wxString& show() const
+ {
+ return errorMessage;
+ }
+ Severity getSeverity() const
+ {
+ return m_severity;
+ }
+private:
+ const wxString errorMessage;
+ const Severity m_severity;
+};
}
diff --git a/shared/zstring.cpp b/shared/zstring.cpp
index 6b2b68c6..9909abb9 100644
--- a/shared/zstring.cpp
+++ b/shared/zstring.cpp
@@ -1,8 +1,8 @@
#include "zstring.h"
+#include <stdexcept>
#ifdef FFS_WIN
#include <wx/msw/wrapwin.h> //includes "windows.h"
-#include <stdexcept>
#endif //FFS_WIN
#ifdef __WXDEBUG__
@@ -27,12 +27,12 @@ AllocationCount::~AllocationCount()
leakingStrings += wxT("\"\n");
}
- MessageBox(NULL, wxString(wxT("Memory leak detected! (No problem if it occurs while Unit testing only!)")) + wxT("\n\n")
+ MessageBox(NULL, wxString(wxT("Memory leak detected!")) + wxT("\n\n")
+ wxT("Candidates:\n") + leakingStrings,
wxString::Format(wxT("%i"), activeStrings.size()), 0);
}
#else
- std::abort();
+ throw std::logic_error("Memory leak!");
#endif
}
@@ -198,7 +198,8 @@ Zstring& Zstring::Trim(bool fromRight)
if (descr->refCount > 1) //allocate new string
*this = Zstring(cursor, thisLen - diff);
else
- { //overwrite this string
+ {
+ //overwrite this string
::memmove(strBegin, cursor, (thisLen - diff + 1) * sizeof(DefaultChar)); //note: do not simply let data point to different location: this corrupts reserve()!
descr->length -= diff;
}
@@ -307,7 +308,8 @@ Zstring& Zstring::replace(size_t pos1, size_t n1, const DefaultChar* str, size_t
const size_t newLen = oldLen - n1 + n2;
if (newLen > oldLen || descr->refCount > 1)
- { //allocate a new string
+ {
+ //allocate a new string
StringDescriptor* newDescr = allocate(newLen);
//assemble new string with replacement
@@ -342,7 +344,8 @@ Zstring& Zstring::operator=(const DefaultChar* source)
if (descr->refCount > 1 || descr->capacity < sourceLen) //allocate new string
*this = Zstring(source, sourceLen);
else
- { //overwrite this string
+ {
+ //overwrite this string
::memcpy(data(), source, (sourceLen + 1) * sizeof(DefaultChar)); //include null-termination
descr->length = sourceLen;
}
@@ -355,7 +358,8 @@ Zstring& Zstring::assign(const DefaultChar* source, size_t len)
if (descr->refCount > 1 || descr->capacity < len) //allocate new string
*this = Zstring(source, len);
else
- { //overwrite this string
+ {
+ //overwrite this string
::memcpy(data(), source, len * sizeof(DefaultChar)); //don't know if source is null-terminated
data()[len] = 0; //include null-termination
descr->length = len;
@@ -412,7 +416,8 @@ void Zstring::reserve(size_t capacityNeeded) //make unshared and check capacity
assert(capacityNeeded != 0);
if (descr->refCount > 1)
- { //allocate a new string
+ {
+ //allocate a new string
const size_t oldLength = length();
assert(oldLength <= getCapacityToAllocate(capacityNeeded));
@@ -425,7 +430,8 @@ void Zstring::reserve(size_t capacityNeeded) //make unshared and check capacity
descr = newDescr;
}
else if (descr->capacity < capacityNeeded)
- { //try to resize the current string (allocate anew if necessary)
+ {
+ //try to resize the current string (allocate anew if necessary)
const size_t newCapacity = getCapacityToAllocate(capacityNeeded);
#ifdef __WXDEBUG__
diff --git a/shared/zstring.h b/shared/zstring.h
index 018ca42e..9c7c2245 100644
--- a/shared/zstring.h
+++ b/shared/zstring.h
@@ -13,6 +13,7 @@
#include <new>
#include <stdlib.h>
#include <vector>
+#include <sstream>
#ifdef __WXDEBUG__
#include <set>
@@ -22,8 +23,10 @@
#ifdef ZSTRING_CHAR
typedef char DefaultChar; //use char strings
+#define DefaultStr(x) x //
#elif defined ZSTRING_WIDE_CHAR
typedef wchar_t DefaultChar; //use wide character strings
+#define DefaultStr(x) L ## x //
#endif
@@ -123,6 +126,10 @@ private:
};
+template <class T>
+Zstring numberToZstring(const T& number); //convert number to Zstring
+
+
//#######################################################################################
//begin of implementation
@@ -146,13 +153,13 @@ int defaultCompare(const char* str1, const char* str2, const size_t count)
}
inline
-char* defaultStrFind(const char* str1, const char* str2)
+const char* defaultStrFind(const char* str1, const char* str2)
{
return strstr(str1, str2);
}
inline
-char* defaultStrFind(const char* str1, int ch)
+const char* defaultStrFind(const char* str1, int ch)
{
return strchr(str1, ch);
}
@@ -236,6 +243,7 @@ public:
private:
AllocationCount() {}
+ AllocationCount(const AllocationCount&);
~AllocationCount();
wxCriticalSection lockActStrings;
@@ -253,11 +261,12 @@ size_t getCapacityToAllocate(const size_t length)
inline
Zstring::StringDescriptor* Zstring::allocate(const size_t newLength)
-{ //allocate and set data for new string
+{
+ //allocate and set data for new string
const size_t newCapacity = getCapacityToAllocate(newLength);
assert(newCapacity);
- StringDescriptor* newDescr = static_cast<StringDescriptor*>(::malloc(sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar))); //use C-memory functions because of realloc()
+ StringDescriptor* const newDescr = static_cast<StringDescriptor*>(::malloc(sizeof(StringDescriptor) + (newCapacity + 1) * sizeof(DefaultChar))); //use C-memory functions because of realloc()
if (newDescr == NULL)
throw std::bad_alloc();
@@ -288,6 +297,7 @@ Zstring::Zstring()
inline
+
Zstring::Zstring(const DefaultChar* source)
{
initAndCopy(source, defaultLength(source));
@@ -671,4 +681,17 @@ const Zstring Zstring::operator+(const DefaultChar ch) const
}
+template <class T>
+inline
+Zstring numberToZstring(const T& number) //convert number to string the C++ way
+{
+#ifdef ZSTRING_CHAR
+ std::stringstream ss;
+#elif defined ZSTRING_WIDE_CHAR
+ std::wstringstream ss;
+#endif
+ ss << number;
+ return Zstring(ss.str().c_str(), ss.str().length());
+}
+
#endif // ZSTRING_H_INCLUDED
bgstack15