• R/O
  • SSH
  • HTTPS

jyeipegyuu: 提交


Commit MetaInfo

修订版18 (tree)
时间2010-10-11 22:26:23
作者berupon

Log Message

GUIで、圧縮設定を調整して結果を確認出来るアプリケーションの作成開始。

更改概述

差异

--- misc.h (revision 17)
+++ misc.h (revision 18)
@@ -49,8 +49,8 @@
4949
5050 int LOCO_IPredictor(int left, int above, int upperLeft)
5151 {
52- int minLeftAbove = std::min(left, above);
53- int maxLeftAbove = std::max(left, above);
52+ int minLeftAbove = std::min<int>(left, above);
53+ int maxLeftAbove = std::max<int>(left, above);
5454 if (upperLeft > maxLeftAbove) {
5555 return minLeftAbove;
5656 }else if (upperLeft < minLeftAbove) {
@@ -220,7 +220,7 @@
220220 int hists[1024];
221221 int phists[1024];
222222 int mhists[1024];
223- int zeroRepeatHist[1024*4];
223+ int zeroRepeatHist[1024*128];
224224
225225 size_t zeroOneOnlyAreaHist[2];
226226 size_t nonZeroOneOnlyAreaHist[1024];
@@ -234,6 +234,13 @@
234234
235235 static const size_t DC_BLOCKCOUNT_BORDER = 8192;
236236
237+#define COMBINE_ZERO_FLAGS 0 // 各周波数の01領域をまとめて圧縮するテスト。逆に圧縮率が落ちてしまう。。
238+
239+#if COMBINE_ZERO_FLAGS
240+std::vector<size_t> zeroFlagCompressedSizes;
241+std::vector<int> zeroFlagValues;
242+#endif
243+
237244 size_t compressSub(
238245 int* src,
239246 const int* pZeroOneInfos,
@@ -253,7 +260,7 @@
253260
254261 int mini = cinfo.mini;
255262 int maxi = cinfo.maxi;
256- size_t max = std::max(maxi, std::abs(mini));
263+ size_t max = std::max<int>(maxi, std::abs(mini));
257264
258265 int* hists = cinfo.hists;
259266 int* phists = cinfo.phists;
@@ -322,7 +329,10 @@
322329 }
323330 encodedValueSizes[0] = blockCount*blockSize;
324331 Encode(&values[0], values.size(), 1, 0, tmp2, encodedValueSizes[0]);
325-
332+#if COMBINE_ZERO_FLAGS
333+ zeroFlagValues.insert(zeroFlagValues.end(), values.begin(), values.end());
334+ zeroFlagCompressedSizes.push_back(encodedValueSizes[0]);
335+#endif
326336 values.clear();
327337 int maxV = 0;
328338 for (size_t i=0; i<blockCount; ++i) {
@@ -330,7 +340,7 @@
330340 if (!pZeroOneInfos[i]) {
331341 for (size_t j=0; j<blockSize; ++j) {
332342 int val = src[i*blockSize+j];
333- maxV = std::max(maxV, val);
343+ maxV = std::max<int>(maxV, val);
334344 cinfo.nonZeroOneOnlyAreaHist[val]++;
335345 values.push_back(val);
336346 }
@@ -548,8 +558,8 @@
548558 size_t srcCount = blockCount * blockSize;
549559 for (size_t j=0; j<srcCount; ++j) {
550560 int val = from[j];
551- mini = std::min(val, mini);
552- maxi = std::max(val, maxi);
561+ mini = std::min<int>(val, mini);
562+ maxi = std::max<int>(val, maxi);
553563 if (val == 0) {
554564 ++zeroRepeat;
555565 }else {
@@ -573,7 +583,7 @@
573583 }
574584 ci.mini = mini;
575585 ci.maxi = maxi;
576- ci.max = std::max(maxi, std::abs(mini));
586+ ci.max = std::max<int>(maxi, std::abs(mini));
577587 ci.signFlagsCount = count - oldCount;
578588 from += srcCount;
579589 }
@@ -604,7 +614,13 @@
604614 progress += compressSub(from, p01, 1<<(i-zeroOneLimit), totalBlockCount, blockSize, dest+progress, destLen-progress, tmp1, tmp2, tmp3, compressInfos[i]);
605615 from += totalBlockCount * blockSize;
606616 }
607-
617+
618+#if COMBINE_ZERO_FLAGS
619+ std::vector<unsigned char> tmp(10000);
620+ int compressedSize = tmp.size();
621+ Encode(&zeroFlagValues[0], zeroFlagValues.size(), 1, 0, &tmp[0], compressedSize);
622+#endif
623+
608624 return progress;
609625 }
610626
--- encode.h (revision 17)
+++ encode.h (revision 18)
@@ -18,6 +18,7 @@
1818 return ret;
1919 }
2020
21+// quantize blocks...
2122 template <typename T>
2223 void encode(
2324 Quantizer& quantizer,
@@ -62,11 +63,11 @@
6263 predictor.average = sum / 8;
6364 gather(srcLine, inLineOffsetBytes, values);
6465 predictor.horizontal(values, tmps);
65- sum = sumOfAbsolutes(tmps);
66- predictor.horizontalUp(values, tmps);
67- sum = sumOfAbsolutes(tmps);
68- predictor.dc(values, tmps);
69- sum = sumOfAbsolutes(tmps);
66+ //sum = sumOfAbsolutes(tmps);
67+ //predictor.horizontalUp(values, tmps);
68+ //sum = sumOfAbsolutes(tmps);
69+ //predictor.dc(values, tmps);
70+ //sum = sumOfAbsolutes(tmps);
7071 dct_8x8(tmps, tmps2);
7172 quantizer.quantize(tmps);
7273 scatter(destLine, outLineOffsetBytes, tmps);
@@ -98,6 +99,7 @@
9899 gather(srcLine, inLineOffsetBytes, values);
99100 dct_8x8(values, tmps);
100101 quantizer.quantize(values);
102+//values[0][0] = 100;
101103 scatter(destLine, outLineOffsetBytes, values);
102104 srcLine += 8; destLine += 8;
103105 }
--- Quantizer.cpp (revision 17)
+++ Quantizer.cpp (revision 18)
@@ -36,7 +36,7 @@
3636 27, 29, 31, 33, 36, 38, 40, 42,
3737 };
3838
39-namespace {
39+namespace impl {
4040
4141 int div(int n, int d)
4242 {
@@ -76,7 +76,7 @@
7676 if (useQuantMatrix) {
7777 for (size_t i=0; i<8; ++i) {
7878 for (size_t j=0; j<8; ++j) {
79- quant8_table[i*8+j] = div(quant8_table[i*8+j] << 4, QUANT8_INTRA_MATRIX[i][j]);
79+ quant8_table[i*8+j] = impl::div(quant8_table[i*8+j] << 4, QUANT8_INTRA_MATRIX[i][j]);
8080 dequant8_table[i*8+j] *= QUANT8_INTRA_MATRIX[i][j];
8181 }
8282 }
--- main.cpp (revision 17)
+++ main.cpp (revision 18)
@@ -98,6 +98,7 @@
9898 unsigned char* pSignFlags = &signFlags[0];
9999 size_t signFlagCount = collectInfos(pWork2, totalBlockCount, pSignFlags, compressInfos);
100100
101+ // AC係数が0か1だけの場合にそこを纏めて圧縮する。低周波成分はさすがに01だけでは無い事が多い。ただある程度以上の高周波は含んでいないブロックが多い場合がある。
101102 size_t zeroOneLimit = 2;
102103 std::vector<int> zeroOneInfos(totalBlockCount);
103104 std::vector<int> allZeroOneInfos(totalBlockCount * 8);
--- decode.h (revision 17)
+++ decode.h (revision 18)
@@ -60,8 +60,9 @@
6060 for (size_t x=0; x<hBlocks; ++x) {
6161
6262 gather(srcLine, inLineOffsetBytes, values);
63-
63+
6464 quantizer.dequantize(values);
65+
6566 idct_8x8(values, tmps);
6667 for (size_t i=0; i<8; ++i) {
6768 for (size_t j=0; j<8; ++j) {
--- ImageCompressionAnalyzer/stdafx.h (nonexistent)
+++ ImageCompressionAnalyzer/stdafx.h (revision 18)
@@ -0,0 +1,41 @@
1+// stdafx.h : include file for standard system include files,
2+// or project specific include files that are used frequently, but
3+// are changed infrequently
4+//
5+
6+#pragma once
7+
8+// Change these values to use different versions
9+#define WINVER 0x0500
10+#define _WIN32_WINNT 0x0501
11+#define _WIN32_IE 0x0501
12+#define _RICHEDIT_VER 0x0200
13+
14+#include <atlbase.h>
15+#include <atlapp.h>
16+
17+extern CAppModule _Module;
18+
19+#include <atlwin.h>
20+
21+#include <atlddx.h>
22+#include <atlctrls.h>
23+#include <atlmisc.h>
24+#include <atlcrack.h>
25+
26+template <typename T>
27+__forceinline void OffsetPtr(T*& ptr, int offsetBytes)
28+{
29+ ptr = (T*) ((const char*)ptr + offsetBytes);
30+}
31+
32+#if defined _M_IX86
33+ #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
34+#elif defined _M_IA64
35+ #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
36+#elif defined _M_X64
37+ #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
38+#else
39+ #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
40+#endif
41+
--- ImageCompressionAnalyzer/MainFrm.h (nonexistent)
+++ ImageCompressionAnalyzer/MainFrm.h (revision 18)
@@ -0,0 +1,139 @@
1+// MainFrm.h : interface of the CMainFrame class
2+//
3+/////////////////////////////////////////////////////////////////////////////
4+
5+#pragma once
6+
7+#include <atlframe.h>
8+#include <atlsplit.h>
9+#include <atlctrls.h>
10+#include <atlctrlx.h>
11+#include <atlctrlw.h>
12+
13+#include "resource.h"
14+
15+struct Setting;
16+
17+class CMainFrame : public CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>,
18+ public CMessageFilter, public CIdleHandler
19+{
20+public:
21+ CMainFrame();
22+ ~CMainFrame();
23+
24+ DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
25+
26+ CSplitterWindow m_splitter;
27+ CPaneContainer m_pane;
28+ class CSettingView* m_pSettingView;
29+ class CImageView* m_pImageView;
30+ CCommandBarCtrl m_CmdBar;
31+ CMultiPaneStatusBarCtrl m_wndStatusBar;
32+
33+ virtual BOOL PreTranslateMessage(MSG* pMsg);
34+
35+ virtual BOOL OnIdle()
36+ {
37+ UIUpdateToolBar();
38+ return FALSE;
39+ }
40+
41+ BEGIN_UPDATE_UI_MAP(CMainFrame)
42+ UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
43+ UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
44+ UPDATE_ELEMENT(ID_VIEW_SETTINGPANE, UPDUI_MENUPOPUP)
45+ END_UPDATE_UI_MAP()
46+
47+ BEGIN_MSG_MAP(CMainFrame)
48+ MESSAGE_HANDLER(WM_CREATE, OnCreate)
49+ MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
50+ COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
51+ COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
52+ COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
53+ COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
54+ COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
55+ COMMAND_ID_HANDLER(ID_VIEW_SETTINGPANE, OnViewSettingPane)
56+ COMMAND_ID_HANDLER(ID_PANE_CLOSE, OnPaneClose)
57+ COMMAND_ID_HANDLER(ID_FILE_OPEN, OnFileOpen)
58+ CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
59+ CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
60+ END_MSG_MAP()
61+
62+// Handler prototypes (uncomment arguments if needed):
63+// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
64+// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
65+// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
66+
67+ LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
68+
69+ LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
70+ {
71+ // unregister message filtering and idle updates
72+ CMessageLoop* pLoop = _Module.GetMessageLoop();
73+ ATLASSERT(pLoop != NULL);
74+ pLoop->RemoveMessageFilter(this);
75+ pLoop->RemoveIdleHandler(this);
76+
77+ bHandled = FALSE;
78+ return 1;
79+ }
80+
81+ LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
82+ {
83+ PostMessage(WM_CLOSE);
84+ return 0;
85+ }
86+
87+ LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
88+ {
89+ // TODO: add code to initialize document
90+
91+ return 0;
92+ }
93+
94+ LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
95+ {
96+ static BOOL bVisible = TRUE; // initially visible
97+ bVisible = !bVisible;
98+ CReBarCtrl rebar = m_hWndToolBar;
99+ int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1); // toolbar is 2nd added band
100+ rebar.ShowBand(nBandIndex, bVisible);
101+ UISetCheck(ID_VIEW_TOOLBAR, bVisible);
102+ UpdateLayout();
103+ return 0;
104+ }
105+
106+ LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
107+ {
108+ BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
109+ ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
110+ UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
111+ UpdateLayout();
112+ return 0;
113+ }
114+
115+ LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
116+
117+ LRESULT OnViewSettingPane(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
118+ {
119+ bool bShow = (m_splitter.GetSinglePaneMode() != SPLIT_PANE_NONE);
120+ m_splitter.SetSinglePaneMode(bShow ? SPLIT_PANE_NONE : SPLIT_PANE_RIGHT);
121+ UISetCheck(ID_VIEW_SETTINGPANE, bShow);
122+
123+ return 0;
124+ }
125+
126+ LRESULT OnPaneClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND hWndCtl, BOOL& /*bHandled*/)
127+ {
128+ if(hWndCtl == m_pane.m_hWnd)
129+ {
130+ m_splitter.SetSinglePaneMode(SPLIT_PANE_RIGHT);
131+ UISetCheck(ID_VIEW_SETTINGPANE, 0);
132+ }
133+
134+ return 0;
135+ }
136+
137+ void OnSettingChange(const Setting& s);
138+ LRESULT OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
139+};
--- ImageCompressionAnalyzer/AboutDlg.h (nonexistent)
+++ ImageCompressionAnalyzer/AboutDlg.h (revision 18)
@@ -0,0 +1,34 @@
1+// aboutdlg.h : interface of the CAboutDlg class
2+//
3+/////////////////////////////////////////////////////////////////////////////
4+
5+#pragma once
6+
7+class CAboutDlg : public CDialogImpl<CAboutDlg>
8+{
9+public:
10+ enum { IDD = IDD_ABOUTBOX };
11+
12+ BEGIN_MSG_MAP(CAboutDlg)
13+ MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
14+ COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
15+ COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
16+ END_MSG_MAP()
17+
18+// Handler prototypes (uncomment arguments if needed):
19+// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
20+// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
21+// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
22+
23+ LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
24+ {
25+ CenterWindow(GetParent());
26+ return TRUE;
27+ }
28+
29+ LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
30+ {
31+ EndDialog(wID);
32+ return 0;
33+ }
34+};
--- ImageCompressionAnalyzer/SettingView.cpp (nonexistent)
+++ ImageCompressionAnalyzer/SettingView.cpp (revision 18)
@@ -0,0 +1,76 @@
1+// This file was generated by WTL Dialog wizard
2+// SettingView.cpp : Implementation of CSettingView
3+
4+#include "stdafx.h"
5+#include "SettingView.h"
6+
7+#include "setting.h"
8+
9+// CSettingView
10+CSettingView::CSettingView()
11+{
12+}
13+
14+CSettingView::~CSettingView()
15+{
16+}
17+
18+LRESULT CSettingView::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
19+{
20+ DoDataExchange();
21+ m_wndSpinQpShift.SetRange(0, 10);
22+ m_wndSpinQpRemain.SetRange(0, 5);
23+ m_wndSpinHblockness.SetRange(0, 8);
24+ m_wndSpinVblockness.SetRange(0, 8);
25+
26+ m_wndSpinZeroOneLimit.SetRange(0, 7);
27+ return 1; // Let the system set the focus
28+}
29+
30+
31+LRESULT CSettingView::OnCommand(UINT codeNotify, int id, HWND hwndCtl)
32+{
33+ switch (id) {
34+ case IDC_CHECK_quantize_matrix:
35+ case IDC_CHECK_reorder_by_frequency:
36+ case IDC_CHECK_enable_DC_prediction:
37+ OnSettingChange();
38+ break;
39+ }
40+ return 0;
41+}
42+
43+LRESULT CSettingView::OnVScroll(int code, short pos, HWND hwndCtl)
44+{
45+ if (code != SB_THUMBPOSITION) {
46+ return 0;
47+ }
48+ if (0
49+ || hwndCtl == m_wndSpinQpShift.m_hWnd
50+ || hwndCtl == m_wndSpinQpRemain.m_hWnd
51+ || hwndCtl == m_wndSpinHblockness.m_hWnd
52+ || hwndCtl == m_wndSpinVblockness.m_hWnd
53+ || hwndCtl == m_wndSpinZeroOneLimit.m_hWnd
54+ )
55+ {
56+ OnSettingChange();
57+ }
58+ return 0;
59+}
60+
61+void CSettingView::OnSettingChange()
62+{
63+ if (m_onSettingChangeDelegate.empty())
64+ return;
65+
66+ Setting s;
67+ s.qp = m_wndSpinQpShift.GetPos() * 6 + m_wndSpinQpRemain.GetPos();
68+ s.hBlockness = m_wndSpinHblockness.GetPos();
69+ s.vBlockness = m_wndSpinVblockness.GetPos();
70+ s.useQuantMatrix = m_wndButtonQuantizeMatrix.GetCheck();
71+ s.reorderByFrequency = m_wndButtonReorderByFrequency.GetCheck();
72+ s.enableDCprediction = m_wndButtonEnableDCPrediction.GetCheck();
73+ s.zeroOneLimit = m_wndSpinZeroOneLimit.GetPos();
74+
75+ m_onSettingChangeDelegate(s);
76+}
--- ImageCompressionAnalyzer/stdint.h (nonexistent)
+++ ImageCompressionAnalyzer/stdint.h (revision 18)
@@ -0,0 +1,247 @@
1+// ISO C9x compliant stdint.h for Microsoft Visual Studio
2+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
3+//
4+// Copyright (c) 2006-2008 Alexander Chemeris
5+//
6+// Redistribution and use in source and binary forms, with or without
7+// modification, are permitted provided that the following conditions are met:
8+//
9+// 1. Redistributions of source code must retain the above copyright notice,
10+// this list of conditions and the following disclaimer.
11+//
12+// 2. Redistributions in binary form must reproduce the above copyright
13+// notice, this list of conditions and the following disclaimer in the
14+// documentation and/or other materials provided with the distribution.
15+//
16+// 3. The name of the author may be used to endorse or promote products
17+// derived from this software without specific prior written permission.
18+//
19+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
20+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+//
30+///////////////////////////////////////////////////////////////////////////////
31+
32+#ifndef _MSC_VER // [
33+#error "Use this header only with Microsoft Visual C++ compilers!"
34+#endif // _MSC_VER ]
35+
36+#ifndef _MSC_STDINT_H_ // [
37+#define _MSC_STDINT_H_
38+
39+#if _MSC_VER > 1000
40+#pragma once
41+#endif
42+
43+#include <limits.h>
44+
45+// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
46+// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
47+// or compiler give many errors like this:
48+// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
49+#ifdef __cplusplus
50+extern "C" {
51+#endif
52+# include <wchar.h>
53+#ifdef __cplusplus
54+}
55+#endif
56+
57+// Define _W64 macros to mark types changing their size, like intptr_t.
58+#ifndef _W64
59+# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
60+# define _W64 __w64
61+# else
62+# define _W64
63+# endif
64+#endif
65+
66+
67+// 7.18.1 Integer types
68+
69+// 7.18.1.1 Exact-width integer types
70+
71+// Visual Studio 6 and Embedded Visual C++ 4 doesn't
72+// realize that, e.g. char has the same size as __int8
73+// so we give up on __intX for them.
74+#if (_MSC_VER < 1300)
75+ typedef signed char int8_t;
76+ typedef signed short int16_t;
77+ typedef signed int int32_t;
78+ typedef unsigned char uint8_t;
79+ typedef unsigned short uint16_t;
80+ typedef unsigned int uint32_t;
81+#else
82+ typedef signed __int8 int8_t;
83+ typedef signed __int16 int16_t;
84+ typedef signed __int32 int32_t;
85+ typedef unsigned __int8 uint8_t;
86+ typedef unsigned __int16 uint16_t;
87+ typedef unsigned __int32 uint32_t;
88+#endif
89+typedef signed __int64 int64_t;
90+typedef unsigned __int64 uint64_t;
91+
92+
93+// 7.18.1.2 Minimum-width integer types
94+typedef int8_t int_least8_t;
95+typedef int16_t int_least16_t;
96+typedef int32_t int_least32_t;
97+typedef int64_t int_least64_t;
98+typedef uint8_t uint_least8_t;
99+typedef uint16_t uint_least16_t;
100+typedef uint32_t uint_least32_t;
101+typedef uint64_t uint_least64_t;
102+
103+// 7.18.1.3 Fastest minimum-width integer types
104+typedef int8_t int_fast8_t;
105+typedef int16_t int_fast16_t;
106+typedef int32_t int_fast32_t;
107+typedef int64_t int_fast64_t;
108+typedef uint8_t uint_fast8_t;
109+typedef uint16_t uint_fast16_t;
110+typedef uint32_t uint_fast32_t;
111+typedef uint64_t uint_fast64_t;
112+
113+// 7.18.1.4 Integer types capable of holding object pointers
114+#ifdef _WIN64 // [
115+ typedef signed __int64 intptr_t;
116+ typedef unsigned __int64 uintptr_t;
117+#else // _WIN64 ][
118+ typedef _W64 signed int intptr_t;
119+ typedef _W64 unsigned int uintptr_t;
120+#endif // _WIN64 ]
121+
122+// 7.18.1.5 Greatest-width integer types
123+typedef int64_t intmax_t;
124+typedef uint64_t uintmax_t;
125+
126+
127+// 7.18.2 Limits of specified-width integer types
128+
129+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
130+
131+// 7.18.2.1 Limits of exact-width integer types
132+#define INT8_MIN ((int8_t)_I8_MIN)
133+#define INT8_MAX _I8_MAX
134+#define INT16_MIN ((int16_t)_I16_MIN)
135+#define INT16_MAX _I16_MAX
136+#define INT32_MIN ((int32_t)_I32_MIN)
137+#define INT32_MAX _I32_MAX
138+#define INT64_MIN ((int64_t)_I64_MIN)
139+#define INT64_MAX _I64_MAX
140+#define UINT8_MAX _UI8_MAX
141+#define UINT16_MAX _UI16_MAX
142+#define UINT32_MAX _UI32_MAX
143+#define UINT64_MAX _UI64_MAX
144+
145+// 7.18.2.2 Limits of minimum-width integer types
146+#define INT_LEAST8_MIN INT8_MIN
147+#define INT_LEAST8_MAX INT8_MAX
148+#define INT_LEAST16_MIN INT16_MIN
149+#define INT_LEAST16_MAX INT16_MAX
150+#define INT_LEAST32_MIN INT32_MIN
151+#define INT_LEAST32_MAX INT32_MAX
152+#define INT_LEAST64_MIN INT64_MIN
153+#define INT_LEAST64_MAX INT64_MAX
154+#define UINT_LEAST8_MAX UINT8_MAX
155+#define UINT_LEAST16_MAX UINT16_MAX
156+#define UINT_LEAST32_MAX UINT32_MAX
157+#define UINT_LEAST64_MAX UINT64_MAX
158+
159+// 7.18.2.3 Limits of fastest minimum-width integer types
160+#define INT_FAST8_MIN INT8_MIN
161+#define INT_FAST8_MAX INT8_MAX
162+#define INT_FAST16_MIN INT16_MIN
163+#define INT_FAST16_MAX INT16_MAX
164+#define INT_FAST32_MIN INT32_MIN
165+#define INT_FAST32_MAX INT32_MAX
166+#define INT_FAST64_MIN INT64_MIN
167+#define INT_FAST64_MAX INT64_MAX
168+#define UINT_FAST8_MAX UINT8_MAX
169+#define UINT_FAST16_MAX UINT16_MAX
170+#define UINT_FAST32_MAX UINT32_MAX
171+#define UINT_FAST64_MAX UINT64_MAX
172+
173+// 7.18.2.4 Limits of integer types capable of holding object pointers
174+#ifdef _WIN64 // [
175+# define INTPTR_MIN INT64_MIN
176+# define INTPTR_MAX INT64_MAX
177+# define UINTPTR_MAX UINT64_MAX
178+#else // _WIN64 ][
179+# define INTPTR_MIN INT32_MIN
180+# define INTPTR_MAX INT32_MAX
181+# define UINTPTR_MAX UINT32_MAX
182+#endif // _WIN64 ]
183+
184+// 7.18.2.5 Limits of greatest-width integer types
185+#define INTMAX_MIN INT64_MIN
186+#define INTMAX_MAX INT64_MAX
187+#define UINTMAX_MAX UINT64_MAX
188+
189+// 7.18.3 Limits of other integer types
190+
191+#ifdef _WIN64 // [
192+# define PTRDIFF_MIN _I64_MIN
193+# define PTRDIFF_MAX _I64_MAX
194+#else // _WIN64 ][
195+# define PTRDIFF_MIN _I32_MIN
196+# define PTRDIFF_MAX _I32_MAX
197+#endif // _WIN64 ]
198+
199+#define SIG_ATOMIC_MIN INT_MIN
200+#define SIG_ATOMIC_MAX INT_MAX
201+
202+#ifndef SIZE_MAX // [
203+# ifdef _WIN64 // [
204+# define SIZE_MAX _UI64_MAX
205+# else // _WIN64 ][
206+# define SIZE_MAX _UI32_MAX
207+# endif // _WIN64 ]
208+#endif // SIZE_MAX ]
209+
210+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
211+#ifndef WCHAR_MIN // [
212+# define WCHAR_MIN 0
213+#endif // WCHAR_MIN ]
214+#ifndef WCHAR_MAX // [
215+# define WCHAR_MAX _UI16_MAX
216+#endif // WCHAR_MAX ]
217+
218+#define WINT_MIN 0
219+#define WINT_MAX _UI16_MAX
220+
221+#endif // __STDC_LIMIT_MACROS ]
222+
223+
224+// 7.18.4 Limits of other integer types
225+
226+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
227+
228+// 7.18.4.1 Macros for minimum-width integer constants
229+
230+#define INT8_C(val) val##i8
231+#define INT16_C(val) val##i16
232+#define INT32_C(val) val##i32
233+#define INT64_C(val) val##i64
234+
235+#define UINT8_C(val) val##ui8
236+#define UINT16_C(val) val##ui16
237+#define UINT32_C(val) val##ui32
238+#define UINT64_C(val) val##ui64
239+
240+// 7.18.4.2 Macros for greatest-width integer constants
241+#define INTMAX_C INT64_C
242+#define UINTMAX_C UINT64_C
243+
244+#endif // __STDC_CONSTANT_MACROS ]
245+
246+
247+#endif // _MSC_STDINT_H_ ]
--- ImageCompressionAnalyzer/ImageCompressionAnalyzer.cpp (nonexistent)
+++ ImageCompressionAnalyzer/ImageCompressionAnalyzer.cpp (revision 18)
@@ -0,0 +1,62 @@
1+// ImageCompressionAnalyzer.cpp : main source file for ImageCompressionAnalyzer.exe
2+//
3+
4+#include "stdafx.h"
5+
6+#include <atlframe.h>
7+#include <atlctrls.h>
8+#include <atldlgs.h>
9+#include <atlctrlw.h>
10+#include <atlctrlx.h>
11+#include <atlsplit.h>
12+
13+#include "resource.h"
14+
15+#include "MainFrm.h"
16+
17+CAppModule _Module;
18+
19+int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
20+{
21+ CMessageLoop theLoop;
22+ _Module.AddMessageLoop(&theLoop);
23+
24+ CMainFrame wndMain;
25+
26+ if(wndMain.CreateEx() == NULL)
27+ {
28+ ATLTRACE(_T("Main window creation failed!\n"));
29+ return 0;
30+ }
31+
32+ wndMain.ShowWindow(nCmdShow);
33+
34+ int nRet = theLoop.Run();
35+
36+ _Module.RemoveMessageLoop();
37+ return nRet;
38+}
39+
40+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
41+{
42+ HRESULT hRes = ::CoInitialize(NULL);
43+// If you are running on NT 4.0 or higher you can use the following call instead to
44+// make the EXE free threaded. This means that calls come in on a random RPC thread.
45+// HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
46+ ATLASSERT(SUCCEEDED(hRes));
47+
48+ // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
49+ ::DefWindowProc(NULL, 0, 0, 0L);
50+
51+ AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES); // add flags to support other controls
52+
53+ hRes = _Module.Init(NULL, hInstance);
54+ ATLASSERT(SUCCEEDED(hRes));
55+
56+ int nRet = Run(lpstrCmdLine, nCmdShow);
57+
58+ _Module.Term();
59+ ::CoUninitialize();
60+
61+ return nRet;
62+}
--- ImageCompressionAnalyzer/ImageView.cpp (nonexistent)
+++ ImageCompressionAnalyzer/ImageView.cpp (revision 18)
@@ -0,0 +1,131 @@
1+#include "stdafx.h"
2+#include "ImageView.h"
3+
4+HBITMAP CreateDIB32(int width, int height, BITMAPINFO& bmi, void*& pBits)
5+{
6+ BITMAPINFOHEADER& header = bmi.bmiHeader;
7+ header.biSize = sizeof(BITMAPINFOHEADER);
8+ header.biWidth = width;
9+ header.biHeight = height;
10+ header.biPlanes = 1;
11+ header.biBitCount = 32;
12+ header.biCompression = BI_RGB;
13+ header.biSizeImage = width * abs(height) * 4;
14+ header.biXPelsPerMeter = 0;
15+ header.biYPelsPerMeter = 0;
16+ header.biClrUsed = 0;
17+ header.biClrImportant = 0;
18+
19+ return ::CreateDIBSection(
20+ (HDC)0,
21+ &bmi,
22+ DIB_RGB_COLORS,
23+ &pBits,
24+ NULL,
25+ 0
26+ );
27+}
28+
29+void CImageView::SetupDIB()
30+{
31+ CWindow wnd(GetDesktopWindow());
32+ HDC hDC = wnd.GetDC();
33+ int width = GetDeviceCaps(hDC, HORZRES) + 10;
34+ int height = GetDeviceCaps(hDC, VERTRES) + 10;
35+ wnd.ReleaseDC(hDC);
36+
37+ // TopDown形式
38+ if (m_hBMP) {
39+ DeleteObject(m_hBMP);
40+ m_hBMP = 0;
41+ }
42+ m_hBMP = CreateDIB32(width, -height, m_bmi, m_pBits);
43+
44+ if (m_memDC.m_hDC) {
45+ m_memDC.DeleteDC();
46+ }
47+ HDC dc = GetDC();
48+ m_memDC.CreateCompatibleDC(dc);
49+ m_memDC.SetMapMode(GetMapMode(dc));
50+ ReleaseDC(dc);
51+ m_memDC.SelectBitmap(m_hBMP);
52+
53+}
54+
55+
56+LRESULT CImageView::OnCreate(LPCREATESTRUCT lpCreateStruct)
57+{
58+ m_hBMP = 0;
59+ SetupDIB();
60+ return 0;
61+}
62+
63+LRESULT CImageView::OnDestroy(void)
64+{
65+ if (m_hBMP) {
66+ DeleteObject(m_hBMP);
67+ m_hBMP = 0;
68+ }
69+ //You should call SetMsgHandled(FALSE) or set bHandled = FALSE for the main window of your application
70+ SetMsgHandled(FALSE);
71+ return 0;
72+}
73+
74+LRESULT CImageView::OnEraseBkgnd(HDC hdc)
75+{
76+ return TRUE; // background is erased
77+}
78+
79+LRESULT CImageView::OnSize(UINT state, CSize Size)
80+{
81+ if (IsWindow() && Size.cx != 0 && Size.cy != 0 && m_hBMP) {
82+ Render();
83+ }
84+ return 0;
85+}
86+
87+LRESULT CImageView::OnDisplayChange(UINT bitsPerPixel, CSize Size)
88+{
89+ if (m_bmi.bmiHeader.biWidth < Size.cx || abs(m_bmi.bmiHeader.biHeight) < Size.cy) {
90+ SetupDIB();
91+ Render();
92+ }
93+ return 0;
94+}
95+
96+LRESULT CImageView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
97+{
98+ CPaintDC dc(m_hWnd);
99+ CRect rect = dc.m_ps.rcPaint;
100+
101+ dc.BitBlt(
102+ rect.left,
103+ rect.top,
104+ rect.Width(),
105+ rect.Height(),
106+ m_memDC,
107+ rect.left,
108+ rect.top,
109+ SRCCOPY
110+ );
111+ return 0;
112+}
113+
114+void CImageView::Render()
115+{
116+}
117+
118+void CImageView::SetImage(size_t width, size_t height, const unsigned char* p)
119+{
120+ unsigned int* pDest = (unsigned int*)m_pBits;
121+ int lineOffsetBytes = m_bmi.bmiHeader.biWidth * 4;
122+ for (size_t y=0; y<height; ++y) {
123+ for (size_t x=0; x<width; ++x) {
124+ unsigned char c = *p++;
125+ pDest[x] = RGB(c,c,c);
126+ }
127+ OffsetPtr(pDest, lineOffsetBytes);
128+ }
129+
130+ Invalidate();
131+}
--- ImageCompressionAnalyzer/SettingView.h (nonexistent)
+++ ImageCompressionAnalyzer/SettingView.h (revision 18)
@@ -0,0 +1,59 @@
1+// This file was generated by WTL Dialog wizard
2+// SettingView.h : Declaration of the CSettingView
3+
4+#pragma once
5+
6+#include "resource.h" // main symbols
7+#include <atlcrack.h>
8+#include "fastdelegate.h"
9+
10+struct Setting;
11+// CSettingView
12+
13+class CSettingView :
14+ public CDialogImpl<CSettingView>,
15+ public CWinDataExchange<CSettingView>
16+{
17+ CUpDownCtrl m_wndSpinQpShift;
18+ CUpDownCtrl m_wndSpinQpRemain;
19+ CUpDownCtrl m_wndSpinHblockness;
20+ CUpDownCtrl m_wndSpinVblockness;
21+ CButton m_wndButtonQuantizeMatrix;
22+ CButton m_wndButtonReorderByFrequency;
23+ CButton m_wndButtonEnableDCPrediction;
24+ CUpDownCtrl m_wndSpinZeroOneLimit;
25+ void OnSettingChange();
26+
27+public:
28+ CSettingView();
29+ ~CSettingView();
30+ enum { IDD = IDD_SETTING };
31+
32+ BEGIN_MSG_MAP(CSettingView)
33+ MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
34+ MSG_WM_COMMAND(OnCommand)
35+ MSG_WM_VSCROLL(OnVScroll)
36+ END_MSG_MAP()
37+
38+ BEGIN_DDX_MAP(CSettingView)
39+ DDX_CONTROL_HANDLE(IDC_SPIN_QP_shift, m_wndSpinQpShift)
40+ DDX_CONTROL_HANDLE(IDC_SPIN_QP_remain, m_wndSpinQpRemain)
41+ DDX_CONTROL_HANDLE(IDC_SPIN_hBlockness, m_wndSpinHblockness)
42+ DDX_CONTROL_HANDLE(IDC_SPIN_vBlockness, m_wndSpinVblockness)
43+ DDX_CONTROL_HANDLE(IDC_CHECK_quantize_matrix, m_wndButtonQuantizeMatrix)
44+ DDX_CONTROL_HANDLE(IDC_CHECK_reorder_by_frequency, m_wndButtonReorderByFrequency)
45+ DDX_CONTROL_HANDLE(IDC_CHECK_enable_DC_prediction, m_wndButtonEnableDCPrediction)
46+ DDX_CONTROL_HANDLE(IDC_SPIN_zero_one_limit, m_wndSpinZeroOneLimit)
47+ END_DDX_MAP()
48+ // Handler prototypes:
49+ // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
50+ // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
51+ // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
52+ LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
53+ LRESULT OnCommand(UINT codeNotify, int id, HWND hwndCtl);
54+ LRESULT OnVScroll(int code, short pos, HWND hwndCtl);
55+
56+ fastdelegate::FastDelegate1<const Setting&> m_onSettingChangeDelegate;
57+};
58+
59+
--- ImageCompressionAnalyzer/ImageCompressionAnalyzer.h (nonexistent)
+++ ImageCompressionAnalyzer/ImageCompressionAnalyzer.h (revision 18)
@@ -0,0 +1 @@
1+// ImageCompressionAnalyzer.h
--- ImageCompressionAnalyzer/ImageView.h (nonexistent)
+++ ImageCompressionAnalyzer/ImageView.h (revision 18)
@@ -0,0 +1,42 @@
1+#pragma once
2+
3+class CImageView : public CWindowImpl<CImageView>
4+{
5+ HBITMAP m_hBMP;
6+ BITMAPINFO m_bmi;
7+ void* m_pBits;
8+ CDC m_memDC;
9+ void SetupDIB();
10+ void Render();
11+
12+public:
13+ DECLARE_WND_CLASS_EX(NULL, CS_NOCLOSE|CS_DBLCLKS|CS_OWNDC, (HBRUSH)GetStockObject(NULL_BRUSH)-1)
14+
15+ BOOL PreTranslateMessage(MSG* pMsg)
16+ {
17+ pMsg;
18+ return FALSE;
19+ }
20+
21+ BEGIN_MSG_MAP(CImageCompressionAnalyzerView)
22+ MSG_WM_CREATE(OnCreate)
23+ MSG_WM_DESTROY(OnDestroy)
24+ MSG_WM_ERASEBKGND(OnEraseBkgnd)
25+ MESSAGE_HANDLER(WM_PAINT, OnPaint)
26+ MSG_WM_SIZE(OnSize)
27+ END_MSG_MAP()
28+
29+// Handler prototypes (uncomment arguments if needed):
30+// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
31+// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
32+// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
33+
34+ LRESULT OnCreate(LPCREATESTRUCT lpCreateStruct);
35+ LRESULT OnDestroy(void);
36+ LRESULT OnEraseBkgnd(HDC hdc);
37+ LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
38+ LRESULT OnSize(UINT state, CSize Size);
39+ LRESULT OnDisplayChange(UINT bitsPerPixel, CSize Size);
40+
41+ void SetImage(size_t width, size_t height, const unsigned char* p);
42+};
--- ImageCompressionAnalyzer/setting.h (nonexistent)
+++ ImageCompressionAnalyzer/setting.h (revision 18)
@@ -0,0 +1,13 @@
1+#pragma once
2+
3+struct Setting
4+{
5+ size_t qp;
6+ size_t hBlockness;
7+ size_t vBlockness;
8+ bool useQuantMatrix;
9+ bool reorderByFrequency;
10+ bool enableDCprediction;
11+ size_t zeroOneLimit;
12+};
13+
--- ImageCompressionAnalyzer/stdafx.cpp (nonexistent)
+++ ImageCompressionAnalyzer/stdafx.cpp (revision 18)
@@ -0,0 +1,9 @@
1+// stdafx.cpp : source file that includes just the standard includes
2+// ImageCompressionAnalyzer.pch will be the pre-compiled header
3+// stdafx.obj will contain the pre-compiled type information
4+
5+#include "stdafx.h"
6+
7+#if (_ATL_VER < 0x0700)
8+#include <atlimpl.cpp>
9+#endif //(_ATL_VER < 0x0700)
--- ImageCompressionAnalyzer/MainFrm.cpp (nonexistent)
+++ ImageCompressionAnalyzer/MainFrm.cpp (revision 18)
@@ -0,0 +1,345 @@
1+#include "stdafx.h"
2+#include "MainFrm.h"
3+
4+#include "SettingView.h"
5+#include "ImageView.h"
6+#include "AboutDlg.h"
7+
8+#include <atldlgs.h>
9+
10+CMainFrame::CMainFrame()
11+ :
12+ m_pSettingView(new CSettingView),
13+ m_pImageView(new CImageView)
14+{
15+ m_pSettingView->m_onSettingChangeDelegate.bind(this, &CMainFrame::OnSettingChange);
16+}
17+
18+
19+CMainFrame::~CMainFrame()
20+{
21+ delete m_pSettingView;
22+ delete m_pImageView;
23+}
24+
25+// virtual
26+BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
27+{
28+ if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
29+ return TRUE;
30+
31+ return m_pImageView->PreTranslateMessage(pMsg);
32+}
33+
34+LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
35+{
36+ // create command bar window
37+ HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
38+ // attach menu
39+ m_CmdBar.AttachMenu(GetMenu());
40+ // load command bar images
41+ m_CmdBar.LoadImages(IDR_MAINFRAME);
42+ // remove old menu
43+ SetMenu(NULL);
44+
45+ HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
46+
47+ CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
48+ AddSimpleReBarBand(hWndCmdBar);
49+ AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
50+
51+ // ステータスバーを作成
52+ m_hWndStatusBar = m_wndStatusBar.Create(m_hWnd);
53+ UIAddStatusBar(m_hWndStatusBar);
54+
55+ // ステータスバーにペインを設定
56+ int nPanes[] = {ID_DEFAULT_PANE, 1};
57+ m_wndStatusBar.SetPanes(nPanes, sizeof(nPanes)/sizeof(nPanes[0]));
58+ m_wndStatusBar.SetPaneWidth(1, 200);
59+
60+
61+ m_hWndClient = m_splitter.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
62+
63+ m_pane.SetPaneContainerExtendedStyle(PANECNT_NOBORDER);
64+ m_pane.Create(m_splitter, _T("Setting"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
65+ m_pSettingView->Create(m_pane, rcDefault);
66+ m_pSettingView->SetFont(AtlGetDefaultGuiFont());
67+ m_pane.SetClient(*m_pSettingView);
68+
69+ m_pImageView->Create(m_splitter, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
70+
71+ m_splitter.SetSplitterPanes(m_pane, *m_pImageView);
72+ UpdateLayout();
73+ m_splitter.SetSplitterPos(190);
74+ m_splitter.SetSplitterExtendedStyle(SPLIT_NONINTERACTIVE);
75+
76+ UIAddToolBar(hWndToolBar);
77+ UISetCheck(ID_VIEW_TOOLBAR, 1);
78+ UISetCheck(ID_VIEW_STATUS_BAR, 1);
79+ UISetCheck(ID_VIEW_SETTINGPANE, 1);
80+
81+ // register object for message filtering and idle updates
82+ CMessageLoop* pLoop = _Module.GetMessageLoop();
83+ ATLASSERT(pLoop != NULL);
84+ pLoop->AddMessageFilter(this);
85+ pLoop->AddIdleHandler(this);
86+
87+ return 0;
88+}
89+
90+LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
91+{
92+ CAboutDlg dlg;
93+ dlg.DoModal();
94+ return 0;
95+}
96+
97+#include <assert.h>
98+
99+#include <vector>
100+#include <algorithm>
101+#include <cmath>
102+
103+#include <boost/integer_traits.hpp>
104+using namespace boost;
105+#include "stdint.h"
106+
107+#include "../dct.h"
108+#include "../Quantizer.h"
109+#include "../misc.h"
110+#include "../decode.h"
111+#include "../encode.h"
112+
113+#include "../ReadImage/ReadImage.h"
114+#include "../ReadImage/File.h"
115+
116+bool bImageLoaded = false;
117+ImageInfo imageInfo;
118+unsigned char palettes[256 * 4];
119+std::vector<unsigned char> in;
120+std::vector<unsigned char> out;
121+
122+bool loadImage(LPCTSTR fileName)
123+{
124+ FILE* f = _tfopen(fileName, _T("rb"));
125+ if (!f) {
126+ return false;
127+ }
128+ File fo(f);
129+ ReadImageInfo(fo, imageInfo);
130+ size_t width = imageInfo.width;
131+ size_t height = imageInfo.height;
132+ assert(imageInfo.bitsPerSample == 8 && imageInfo.samplesPerPixel == 1);
133+ const size_t size = width * height;
134+
135+ in.resize(size);
136+ ReadImageData(fo, &in[0], width, palettes);
137+ fclose(f);
138+ for (size_t i=0; i<size; ++i) {
139+ in[i] = palettes[4 * in[i]];
140+ }
141+ return true;
142+}
143+
144+#include "setting.h"
145+
146+size_t encodeDecode(Setting s)
147+{
148+ size_t width = imageInfo.width;
149+ size_t height = imageInfo.height;
150+ const size_t size = width * height;
151+ std::vector<int> work(size);
152+ std::vector<int> work2(size);
153+ out.resize(size);
154+
155+ const size_t hBlockCount = width / 8 + ((width % 8) ? 1 : 0);
156+ const size_t vBlockCount = height / 8 + ((height % 8) ? 1 : 0);
157+ const size_t totalBlockCount = hBlockCount * vBlockCount;
158+
159+ size_t storageSize = work.size()*4*1.1+600;
160+ std::vector<unsigned char> work3(storageSize);
161+ std::vector<unsigned char> work4(storageSize);
162+ std::vector<unsigned char> encoded(storageSize);
163+ std::vector<CompressInfo> compressInfos(8);
164+
165+ Quantizer quantizer;
166+ quantizer.init(s.qp, s.hBlockness, s.vBlockness, s.useQuantMatrix);
167+
168+ size_t totalLen = 0;
169+
170+ // TODO: to design stream byte formats and various JYEIPEGYUU stream classes and implement serialize methods.
171+
172+ // encode
173+ {
174+ unsigned char* dest = &encoded[0];
175+ unsigned char* initialDest = dest;
176+
177+ // TODO: to record stream signature "jyeipegyuu\0"
178+ // TODO: to record streams
179+
180+ int* pWork = &work[0];
181+ int* pWork2 = &work2[0];
182+
183+ // TODO: to record quantizer parameter
184+
185+ // TODO: to add encode options such as quantization table.
186+ encode(quantizer, hBlockCount, vBlockCount, &in[0], width, pWork, width*sizeof(int));
187+
188+ reorderByFrequency(hBlockCount, vBlockCount, pWork, pWork2);
189+
190+ unsigned char enableDCPrediction = s.enableDCprediction;
191+ *dest++ = enableDCPrediction;
192+ if (enableDCPrediction) {
193+ predictEncode(hBlockCount, vBlockCount, pWork2, pWork);
194+ }
195+
196+ std::vector<unsigned char> signFlags(totalBlockCount*64);
197+ unsigned char* pSignFlags = &signFlags[0];
198+ size_t signFlagCount = collectInfos(pWork2, totalBlockCount, pSignFlags, &compressInfos[0]);
199+
200+ // AC係数が0か1だけの場合にそこを纏めて圧縮する。低周波成分はさすがに01だけでは無い事が多い。ただある程度以上の高周波は含んでいないブロックが多い場合がある。
201+ size_t zeroOneLimit = s.zeroOneLimit;
202+ std::vector<int> zeroOneInfos(totalBlockCount);
203+ std::vector<int> allZeroOneInfos(totalBlockCount * 8);
204+ int* pZeroOneInfos = &zeroOneInfos[0];
205+ int* pAllZeroOneInfos = &allZeroOneInfos[0];
206+
207+ // quantizing zero one flags
208+ *dest++ = zeroOneLimit;
209+ if (zeroOneLimit != 0) {
210+ findZeroOneInfos(hBlockCount, vBlockCount, pWork2, pZeroOneInfos, pAllZeroOneInfos, zeroOneLimit);
211+ int encodedSize = totalBlockCount/4;
212+ Encode(pZeroOneInfos, totalBlockCount, 1, 0, &work3[0], encodedSize);
213+ *((uint32_t*)dest) = encodedSize;
214+ dest += 4;
215+ memcpy(dest, &work3[0], encodedSize);
216+ dest += encodedSize;
217+
218+ //encodedSize = totalBlockCount;
219+ //Encode(pAllZeroOneInfos, totalBlockCount, (256>>zeroOneLimit)-1, 0, &work3[0], encodedSize);
220+ //*((uint32_t*)dest) = encodedSize;
221+ //dest += 4;
222+ //memcpy(dest, &work3[0], encodedSize);
223+ //dest += encodedSize;
224+
225+ }else {
226+ pZeroOneInfos = 0;
227+ }
228+ dest += compress(hBlockCount, vBlockCount, pZeroOneInfos, zeroOneLimit, &compressInfos[0], pWork2, (unsigned char*)pWork, &work3[0], &work4[0], dest, encoded.size());
229+
230+ // TODO: to record DCT coefficients sign predictor setting
231+
232+ BitWriter writer(dest+4);
233+ for (size_t i=0; i<signFlagCount; ++i) {
234+ writer.putBit(signFlags[i] != 0);
235+ }
236+ *((uint32_t*)dest) = writer.nBytes();
237+ dest += 4;
238+ dest += writer.nBytes();
239+
240+ totalLen = dest - initialDest;
241+
242+ }
243+
244+ size_t compressedLen = totalLen;
245+
246+ std::fill(work.begin(), work.end(), 0);
247+ std::fill(work2.begin(), work2.end(), 0);
248+ std::vector<unsigned char> tmp(encoded.size());
249+
250+ // decode
251+ {
252+ unsigned char* src = &encoded[0];
253+ int* pWork = &work[0];
254+ int* pWork2 = &work2[0];
255+ size_t destLen = work2.size();
256+
257+ unsigned char enableDCPrediction = *src++;
258+
259+ // zero one flags
260+ unsigned char zeroOneLimit = *src++;
261+ std::vector<int> zeroOneFlags(totalBlockCount*2);
262+ int* pZeroOneFlags = &zeroOneFlags[0];
263+ if (zeroOneLimit != 0) {
264+ uint32_t zeroOneFlagBytes = *(uint32_t*)src;
265+ src += 4;
266+ {
267+ int flagCount = totalBlockCount;
268+ Decode(src, zeroOneFlagBytes, pZeroOneFlags, flagCount);
269+ assert(flagCount == totalBlockCount);
270+ }
271+ src += zeroOneFlagBytes;
272+ }else {
273+ pZeroOneFlags = 0;
274+ }
275+ src += decompress(hBlockCount, vBlockCount, pZeroOneFlags, zeroOneLimit, src, compressedLen, &tmp[0], pWork, pWork2, destLen);
276+
277+ // sign flags
278+ uint32_t signFlagBytes = *(uint32_t*)src;
279+ src += 4;
280+ std::vector<unsigned char> signFlags(signFlagBytes * 8);
281+ unsigned char* pSignFlags = &signFlags[0];
282+ {
283+ BitReader reader(src);
284+ for (size_t i=0; i<signFlagBytes*8; ++i) {
285+ pSignFlags[i] = reader.getBit();
286+ }
287+ size_t pos = 0;
288+ for (size_t i=0; i<totalBlockCount*64; ++i) {
289+ int& val = pWork2[i];
290+ if (val != 0) {
291+ val = pSignFlags[pos++] ? val : -val;
292+ }
293+ }
294+ }
295+
296+ if (enableDCPrediction) {
297+ predictDecode(hBlockCount, vBlockCount, pWork2, pWork);
298+ }
299+
300+ reorderByPosition(hBlockCount, vBlockCount, pWork2, pWork);
301+
302+ decode(quantizer, hBlockCount, vBlockCount, pWork, width*sizeof(int), &out[0], width);
303+ }
304+ unsigned char* pOutput = &out[0];
305+
306+ //FILE* of = _tfopen(_T("out.raw"), _T("wb"));
307+ //fwrite(pOutput, 1, size, of);
308+ //fclose(of);z
309+
310+ _tprintf(_T("%f%% %d bytes"), (100.0 * compressedLen) / size, compressedLen);
311+
312+ return compressedLen;
313+}
314+
315+LRESULT CMainFrame::OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
316+{
317+ CFileDialog dlg(TRUE);
318+ if (dlg.DoModal() != IDOK) {
319+ return 0;
320+ }
321+
322+ if (!loadImage(dlg.m_ofn.lpstrFile)) {
323+ return 0;
324+ }
325+ bImageLoaded = true;
326+
327+ return 0;
328+}
329+
330+void CMainFrame::OnSettingChange(const Setting& s)
331+{
332+ if (!bImageLoaded) {
333+ return;
334+ }
335+ size_t compressedLen = encodeDecode(s);
336+ m_pImageView->SetImage(imageInfo.width, imageInfo.height, &out[0]);
337+
338+ size_t size = imageInfo.width * imageInfo.height;
339+ TCHAR buff[64];
340+ _stprintf(buff, _T("%.2f%% %d bytes"), (100.0 * compressedLen) / size, compressedLen);
341+
342+ m_wndStatusBar.SetPaneText(1, buff);
343+
344+}
345+
--- ImageCompressionAnalyzer/FastDelegateBind.h (nonexistent)
+++ ImageCompressionAnalyzer/FastDelegateBind.h (revision 18)
@@ -0,0 +1,243 @@
1+// FastDelegateBind.h
2+// Helper file for FastDelegates. Provides bind() function, enabling
3+// FastDelegates to be rapidly compared to programs using boost::function and boost::bind.
4+//
5+// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp
6+//
7+// Original author: Jody Hagins.
8+// Minor changes by Don Clugston.
9+//
10+// Warning: The arguments to 'bind' are ignored! No actual binding is performed.
11+// The behaviour is equivalent to boost::bind only when the basic placeholder
12+// arguments _1, _2, _3, etc are used in order.
13+//
14+// HISTORY:
15+// 1.4 Dec 2004. Initial release as part of FastDelegate 1.4.
16+
17+
18+#ifndef FASTDELEGATEBIND_H
19+#define FASTDELEGATEBIND_H
20+#if _MSC_VER > 1000
21+#pragma once
22+#endif // _MSC_VER > 1000
23+
24+////////////////////////////////////////////////////////////////////////////////
25+// FastDelegate bind()
26+//
27+// bind() helper function for boost compatibility.
28+// (Original author: Jody Hagins).
29+//
30+// Add another helper, so FastDelegate can be a dropin replacement
31+// for boost::bind (in a fair number of cases).
32+// Note the elipses, because boost::bind() takes place holders
33+// but FastDelegate does not care about them. Getting the place holder
34+// mechanism to work, and play well with boost is a bit tricky, so
35+// we do the "easy" thing...
36+// Assume we have the following code...
37+// using boost::bind;
38+// bind(&Foo:func, &foo, _1, _2);
39+// we should be able to replace the "using" with...
40+// using fastdelegate::bind;
41+// and everything should work fine...
42+////////////////////////////////////////////////////////////////////////////////
43+
44+#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
45+
46+namespace fastdelegate {
47+
48+//N=0
49+template <class X, class Y, class RetType>
50+FastDelegate< RetType ( ) >
51+bind(
52+ RetType (X::*func)( ),
53+ Y * y,
54+ ...)
55+{
56+ return FastDelegate< RetType ( ) >(y, func);
57+}
58+
59+template <class X, class Y, class RetType>
60+FastDelegate< RetType ( ) >
61+bind(
62+ RetType (X::*func)( ) const,
63+ Y * y,
64+ ...)
65+{
66+ return FastDelegate< RetType ( ) >(y, func);
67+}
68+
69+//N=1
70+template <class X, class Y, class RetType, class Param1>
71+FastDelegate< RetType ( Param1 p1 ) >
72+bind(
73+ RetType (X::*func)( Param1 p1 ),
74+ Y * y,
75+ ...)
76+{
77+ return FastDelegate< RetType ( Param1 p1 ) >(y, func);
78+}
79+
80+template <class X, class Y, class RetType, class Param1>
81+FastDelegate< RetType ( Param1 p1 ) >
82+bind(
83+ RetType (X::*func)( Param1 p1 ) const,
84+ Y * y,
85+ ...)
86+{
87+ return FastDelegate< RetType ( Param1 p1 ) >(y, func);
88+}
89+
90+//N=2
91+template <class X, class Y, class RetType, class Param1, class Param2>
92+FastDelegate< RetType ( Param1 p1, Param2 p2 ) >
93+bind(
94+ RetType (X::*func)( Param1 p1, Param2 p2 ),
95+ Y * y,
96+ ...)
97+{
98+ return FastDelegate< RetType ( Param1 p1, Param2 p2 ) >(y, func);
99+}
100+
101+template <class X, class Y, class RetType, class Param1, class Param2>
102+FastDelegate< RetType ( Param1 p1, Param2 p2 ) >
103+bind(
104+ RetType (X::*func)( Param1 p1, Param2 p2 ) const,
105+ Y * y,
106+ ...)
107+{
108+ return FastDelegate< RetType ( Param1 p1, Param2 p2 ) >(y, func);
109+}
110+
111+//N=3
112+template <class X, class Y, class RetType, class Param1, class Param2, class Param3>
113+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3 ) >
114+bind(
115+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3 ),
116+ Y * y,
117+ ...)
118+{
119+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3 ) >(y, func);
120+}
121+
122+template <class X, class Y, class RetType, class Param1, class Param2, class Param3>
123+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3 ) >
124+bind(
125+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3 ) const,
126+ Y * y,
127+ ...)
128+{
129+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3 ) >(y, func);
130+}
131+
132+//N=4
133+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
134+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) >
135+bind(
136+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ),
137+ Y * y,
138+ ...)
139+{
140+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) >(y, func);
141+}
142+
143+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4>
144+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) >
145+bind(
146+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const,
147+ Y * y,
148+ ...)
149+{
150+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) >(y, func);
151+}
152+
153+//N=5
154+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
155+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) >
156+bind(
157+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ),
158+ Y * y,
159+ ...)
160+{
161+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) >(y, func);
162+}
163+
164+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5>
165+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) >
166+bind(
167+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const,
168+ Y * y,
169+ ...)
170+{
171+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) >(y, func);
172+}
173+
174+//N=6
175+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
176+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) >
177+bind(
178+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ),
179+ Y * y,
180+ ...)
181+{
182+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) >(y, func);
183+}
184+
185+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
186+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) >
187+bind(
188+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const,
189+ Y * y,
190+ ...)
191+{
192+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) >(y, func);
193+}
194+
195+//N=7
196+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
197+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) >
198+bind(
199+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ),
200+ Y * y,
201+ ...)
202+{
203+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) >(y, func);
204+}
205+
206+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
207+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) >
208+bind(
209+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const,
210+ Y * y,
211+ ...)
212+{
213+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) >(y, func);
214+}
215+
216+//N=8
217+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
218+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) >
219+bind(
220+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ),
221+ Y * y,
222+ ...)
223+{
224+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) >(y, func);
225+}
226+
227+template <class X, class Y, class RetType, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
228+FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) >
229+bind(
230+ RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const,
231+ Y * y,
232+ ...)
233+{
234+ return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) >(y, func);
235+}
236+
237+
238+#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
239+
240+} // namespace fastdelegate
241+
242+#endif // !defined(FASTDELEGATEBIND_H)
243+
--- ImageCompressionAnalyzer/resource.h (nonexistent)
+++ ImageCompressionAnalyzer/resource.h (revision 18)
@@ -0,0 +1,33 @@
1+//{{NO_DEPENDENCIES}}
2+// Microsoft Visual C++ generated include file.
3+// Used by ImageCompressionAnalyzer.rc
4+//
5+#define IDD_ABOUTBOX 100
6+#define IDD_SETTING 101
7+#define IDR_MAINFRAME 128
8+#define IDC_SPIN_QP_shift 1001
9+#define IDC_EDIT_QP_shift 1002
10+#define IDC_SPIN_QP_remain 1003
11+#define IDC_EDIT_QP_remain 1004
12+#define IDC_SPIN_hBlockness 1005
13+#define IDC_EDIT_hBlockness 1006
14+#define IDC_SPIN_vBlockness 1007
15+#define IDC_EDIT_vBlockness 1008
16+#define IDC_CHECK_quantize_matrix 1009
17+#define IDC_CHECK_reorder_by_frequency 1010
18+#define IDC_CHECK_enable_DC_prediction 1011
19+#define IDC_SPIN_zero_one_limit 1012
20+#define IDC_EDIT_zero_one_limit 1013
21+#define ID_VIEW_TREEPANE 32774
22+#define ID_VIEW_SETTINGPANE 32775
23+
24+// Next default values for new objects
25+//
26+#ifdef APSTUDIO_INVOKED
27+#ifndef APSTUDIO_READONLY_SYMBOLS
28+#define _APS_NEXT_RESOURCE_VALUE 201
29+#define _APS_NEXT_COMMAND_VALUE 32776
30+#define _APS_NEXT_CONTROL_VALUE 1015
31+#define _APS_NEXT_SYMED_VALUE 101
32+#endif
33+#endif
--- ImageCompressionAnalyzer/FastDelegate.h (nonexistent)
+++ ImageCompressionAnalyzer/FastDelegate.h (revision 18)
@@ -0,0 +1,2108 @@
1+// FastDelegate.h
2+// Efficient delegates in C++ that generate only two lines of asm code!
3+// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp
4+//
5+// - Don Clugston, Mar 2004.
6+// Major contributions were made by Jody Hagins.
7+// History:
8+// 24-Apr-04 1.0 * Submitted to CodeProject.
9+// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack.
10+// * Improved syntax for horrible_cast (thanks Paul Bludov).
11+// * Tested on Metrowerks MWCC and Intel ICL (IA32)
12+// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL.
13+// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5
14+// * Now works on /clr "managed C++" code on VC7, VC7.1
15+// * Comeau C++ now compiles without warnings.
16+// * Prevent the virtual inheritance case from being used on
17+// VC6 and earlier, which generate incorrect code.
18+// * Improved warning and error messages. Non-standard hacks
19+// now have compile-time checks to make them safer.
20+// * implicit_cast used instead of static_cast in many cases.
21+// * If calling a const member function, a const class pointer can be used.
22+// * MakeDelegate() global helper function added to simplify pass-by-value.
23+// * Added fastdelegate.clear()
24+// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates)
25+// 30-Oct-04 1.3 * Support for (non-void) return values.
26+// * No more workarounds in client code!
27+// MSVC and Intel now use a clever hack invented by John Dlugosz:
28+// - The FASTDELEGATEDECLARE workaround is no longer necessary.
29+// - No more warning messages for VC6
30+// * Less use of macros. Error messages should be more comprehensible.
31+// * Added include guards
32+// * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks).
33+// * Now tested on VS 2005 Express Beta, PGI C++
34+// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates.
35+// * <,>,<=,>= comparison operators to allow storage in ordered containers.
36+// * Substantial reduction of code size, especially the 'Closure' class.
37+// * Standardised all the compiler-specific workarounds.
38+// * MFP conversion now works for CodePlay (but not yet supported in the full code).
39+// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1
40+// * New syntax: FastDelegate< int (char *, double) >.
41+// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric).
42+// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium.
43+// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())"
44+// * Fully supported by CodePlay VectorC
45+// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC!
46+// * More optimal assignment,== and != operators for static function pointers.
47+
48+#ifndef FASTDELEGATE_H
49+#define FASTDELEGATE_H
50+#if _MSC_VER > 1000
51+#pragma once
52+#endif // _MSC_VER > 1000
53+
54+#include <memory.h> // to allow <,> comparisons
55+
56+////////////////////////////////////////////////////////////////////////////////
57+// Configuration options
58+//
59+////////////////////////////////////////////////////////////////////////////////
60+
61+// Uncomment the following #define for optimally-sized delegates.
62+// In this case, the generated asm code is almost identical to the code you'd get
63+// if the compiler had native support for delegates.
64+// It will not work on systems where sizeof(dataptr) < sizeof(codeptr).
65+// Thus, it will not work for DOS compilers using the medium model.
66+// It will also probably fail on some DSP systems.
67+#define FASTDELEGATE_USESTATICFUNCTIONHACK
68+
69+// Uncomment the next line to allow function declarator syntax.
70+// It is automatically enabled for those compilers where it is known to work.
71+//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
72+
73+////////////////////////////////////////////////////////////////////////////////
74+// Compiler identification for workarounds
75+//
76+////////////////////////////////////////////////////////////////////////////////
77+
78+// Compiler identification. It's not easy to identify Visual C++ because
79+// many vendors fraudulently define Microsoft's identifiers.
80+#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__)
81+#define FASTDLGT_ISMSVC
82+
83+#if (_MSC_VER <1300) // Many workarounds are required for VC6.
84+#define FASTDLGT_VC6
85+#pragma warning(disable:4786) // disable this ridiculous warning
86+#endif
87+
88+#endif
89+
90+// Does the compiler uses Microsoft's member function pointer structure?
91+// If so, it needs special treatment.
92+// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's
93+// identifier, _MSC_VER. We need to filter Metrowerks out.
94+#if defined(_MSC_VER) && !defined(__MWERKS__)
95+#define FASTDLGT_MICROSOFT_MFP
96+
97+#if !defined(__VECTOR_C)
98+// CodePlay doesn't have the __single/multi/virtual_inheritance keywords
99+#define FASTDLGT_HASINHERITANCE_KEYWORDS
100+#endif
101+#endif
102+
103+// Does it allow function declarator syntax? The following compilers are known to work:
104+#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1
105+#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
106+#endif
107+
108+// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use.
109+#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__)
110+#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
111+#endif
112+
113+// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too.
114+#if defined (__MWERKS__)
115+#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
116+#endif
117+
118+#ifdef __GNUC__ // Workaround GCC bug #8271
119+ // At present, GCC doesn't recognize constness of MFPs in templates
120+#define FASTDELEGATE_GCC_BUG_8271
121+#endif
122+
123+
124+
125+////////////////////////////////////////////////////////////////////////////////
126+// General tricks used in this code
127+//
128+// (a) Error messages are generated by typdefing an array of negative size to
129+// generate compile-time errors.
130+// (b) Warning messages on MSVC are generated by declaring unused variables, and
131+// enabling the "variable XXX is never used" warning.
132+// (c) Unions are used in a few compiler-specific cases to perform illegal casts.
133+// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to
134+// (char *) first to ensure that the correct number of *bytes* are added.
135+//
136+////////////////////////////////////////////////////////////////////////////////
137+// Helper templates
138+//
139+////////////////////////////////////////////////////////////////////////////////
140+
141+
142+namespace fastdelegate {
143+namespace detail { // we'll hide the implementation details in a nested namespace.
144+
145+// implicit_cast< >
146+// I believe this was originally going to be in the C++ standard but
147+// was left out by accident. It's even milder than static_cast.
148+// I use it instead of static_cast<> to emphasize that I'm not doing
149+// anything nasty.
150+// Usage is identical to static_cast<>
151+template <class OutputClass, class InputClass>
152+inline OutputClass implicit_cast(InputClass input){
153+ return input;
154+}
155+
156+// horrible_cast< >
157+// This is truly evil. It completely subverts C++'s type system, allowing you
158+// to cast from any class to any other class. Technically, using a union
159+// to perform the cast is undefined behaviour (even in C). But we can see if
160+// it is OK by checking that the union is the same size as each of its members.
161+// horrible_cast<> should only be used for compiler-specific workarounds.
162+// Usage is identical to reinterpret_cast<>.
163+
164+// This union is declared outside the horrible_cast because BCC 5.5.1
165+// can't inline a function with a nested class, and gives a warning.
166+template <class OutputClass, class InputClass>
167+union horrible_union{
168+ OutputClass out;
169+ InputClass in;
170+};
171+
172+template <class OutputClass, class InputClass>
173+inline OutputClass horrible_cast(const InputClass input){
174+ horrible_union<OutputClass, InputClass> u;
175+ // Cause a compile-time error if in, out and u are not the same size.
176+ // If the compile fails here, it means the compiler has peculiar
177+ // unions which would prevent the cast from working.
178+ typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u)
179+ && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1];
180+ u.in = input;
181+ return u.out;
182+}
183+
184+////////////////////////////////////////////////////////////////////////////////
185+// Workarounds
186+//
187+////////////////////////////////////////////////////////////////////////////////
188+
189+// Backwards compatibility: This macro used to be necessary in the virtual inheritance
190+// case for Intel and Microsoft. Now it just forward-declares the class.
191+#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME;
192+
193+// Prevent use of the static function hack with the DOS medium model.
194+#ifdef __MEDIUM__
195+#undef FASTDELEGATE_USESTATICFUNCTIONHACK
196+#endif
197+
198+// DefaultVoid - a workaround for 'void' templates in VC6.
199+//
200+// (1) VC6 and earlier do not allow 'void' as a default template argument.
201+// (2) They also doesn't allow you to return 'void' from a function.
202+//
203+// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use
204+// when we'd like to use 'void'. We convert it into 'void' and back
205+// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>.
206+// Workaround for (2): On VC6, the code for calling a void function is
207+// identical to the code for calling a non-void function in which the
208+// return value is never used, provided the return value is returned
209+// in the EAX register, rather than on the stack.
210+// This is true for most fundamental types such as int, enum, void *.
211+// Const void * is the safest option since it doesn't participate
212+// in any automatic conversions. But on a 16-bit compiler it might
213+// cause extra code to be generated, so we disable it for all compilers
214+// except for VC6 (and VC5).
215+#ifdef FASTDLGT_VC6
216+// VC6 workaround
217+typedef const void * DefaultVoid;
218+#else
219+// On any other compiler, just use a normal void.
220+typedef void DefaultVoid;
221+#endif
222+
223+// Translate from 'DefaultVoid' to 'void'.
224+// Everything else is unchanged
225+template <class T>
226+struct DefaultVoidToVoid { typedef T type; };
227+
228+template <>
229+struct DefaultVoidToVoid<DefaultVoid> { typedef void type; };
230+
231+// Translate from 'void' into 'DefaultVoid'
232+// Everything else is unchanged
233+template <class T>
234+struct VoidToDefaultVoid { typedef T type; };
235+
236+template <>
237+struct VoidToDefaultVoid<void> { typedef DefaultVoid type; };
238+
239+
240+
241+////////////////////////////////////////////////////////////////////////////////
242+// Fast Delegates, part 1:
243+//
244+// Conversion of member function pointer to a standard form
245+//
246+////////////////////////////////////////////////////////////////////////////////
247+
248+// GenericClass is a fake class, ONLY used to provide a type.
249+// It is vitally important that it is never defined, so that the compiler doesn't
250+// think it can optimize the invocation. For example, Borland generates simpler
251+// code if it knows the class only uses single inheritance.
252+
253+// Compilers using Microsoft's structure need to be treated as a special case.
254+#ifdef FASTDLGT_MICROSOFT_MFP
255+
256+#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS
257+ // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP
258+ // (4 bytes), even when the /vmg option is used. Declaring an empty class
259+ // would give 16 byte pointers in this case....
260+ class __single_inheritance GenericClass;
261+#endif
262+ // ...but for Codeplay, an empty class *always* gives 4 byte pointers.
263+ // If compiled with the /clr option ("managed C++"), the JIT compiler thinks
264+ // it needs to load GenericClass before it can call any of its functions,
265+ // (compiles OK but crashes at runtime!), so we need to declare an
266+ // empty class to make it happy.
267+ // Codeplay and VC4 can't cope with the unknown_inheritance case either.
268+ class GenericClass {};
269+#else
270+ class GenericClass;
271+#endif
272+
273+// The size of a single inheritance member function pointer.
274+const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)());
275+
276+// SimplifyMemFunc< >::Convert()
277+//
278+// A template function that converts an arbitrary member function pointer into the
279+// simplest possible form of member function pointer, using a supplied 'this' pointer.
280+// According to the standard, this can be done legally with reinterpret_cast<>.
281+// For (non-standard) compilers which use member function pointers which vary in size
282+// depending on the class, we need to use knowledge of the internal structure of a
283+// member function pointer, as used by the compiler. Template specialization is used
284+// to distinguish between the sizes. Because some compilers don't support partial
285+// template specialisation, I use full specialisation of a wrapper struct.
286+
287+// general case -- don't know how to convert it. Force a compile failure
288+template <int N>
289+struct SimplifyMemFunc {
290+ template <class X, class XFuncType, class GenericMemFuncType>
291+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
292+ GenericMemFuncType &bound_func) {
293+ // Unsupported member function type -- force a compile failure.
294+ // (it's illegal to have a array with negative size).
295+ typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100];
296+ return 0;
297+ }
298+};
299+
300+// For compilers where all member func ptrs are the same size, everything goes here.
301+// For non-standard compilers, only single_inheritance classes go here.
302+template <>
303+struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE> {
304+ template <class X, class XFuncType, class GenericMemFuncType>
305+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
306+ GenericMemFuncType &bound_func) {
307+#if defined __DMC__
308+ // Digital Mars doesn't allow you to cast between abitrary PMF's,
309+ // even though the standard says you can. The 32-bit compiler lets you
310+ // static_cast through an int, but the DOS compiler doesn't.
311+ bound_func = horrible_cast<GenericMemFuncType>(function_to_bind);
312+#else
313+ bound_func = reinterpret_cast<GenericMemFuncType>(function_to_bind);
314+#endif
315+ return reinterpret_cast<GenericClass *>(pthis);
316+ }
317+};
318+
319+////////////////////////////////////////////////////////////////////////////////
320+// Fast Delegates, part 1b:
321+//
322+// Workarounds for Microsoft and Intel
323+//
324+////////////////////////////////////////////////////////////////////////////////
325+
326+
327+// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay),
328+// need to be treated as a special case.
329+#ifdef FASTDLGT_MICROSOFT_MFP
330+
331+// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1)
332+// at the start of each function for extra safety, but VC6 seems to ICE
333+// intermittently if you do this inside a template.
334+
335+// __multiple_inheritance classes go here
336+// Nasty hack for Microsoft and Intel (IA32 and Itanium)
337+template<>
338+struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > {
339+ template <class X, class XFuncType, class GenericMemFuncType>
340+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
341+ GenericMemFuncType &bound_func) {
342+ // We need to use a horrible_cast to do this conversion.
343+ // In MSVC, a multiple inheritance member pointer is internally defined as:
344+ union {
345+ XFuncType func;
346+ struct {
347+ GenericMemFuncType funcaddress; // points to the actual member function
348+ int delta; // #BYTES to be added to the 'this' pointer
349+ }s;
350+ } u;
351+ // Check that the horrible_cast will work
352+ typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1];
353+ u.func = function_to_bind;
354+ bound_func = u.s.funcaddress;
355+ return reinterpret_cast<GenericClass *>(reinterpret_cast<char *>(pthis) + u.s.delta);
356+ }
357+};
358+
359+// virtual inheritance is a real nuisance. It's inefficient and complicated.
360+// On MSVC and Intel, there isn't enough information in the pointer itself to
361+// enable conversion to a closure pointer. Earlier versions of this code didn't
362+// work for all cases, and generated a compile-time error instead.
363+// But a very clever hack invented by John M. Dlugosz solves this problem.
364+// My code is somewhat different to his: I have no asm code, and I make no
365+// assumptions about the calling convention that is used.
366+
367+// In VC++ and ICL, a virtual_inheritance member pointer
368+// is internally defined as:
369+struct MicrosoftVirtualMFP {
370+ void (GenericClass::*codeptr)(); // points to the actual member function
371+ int delta; // #bytes to be added to the 'this' pointer
372+ int vtable_index; // or 0 if no virtual inheritance
373+};
374+// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the
375+// m_codeptr member is *always* called, regardless of the values of the other
376+// members. (This is *not* true for other compilers, eg GCC, which obtain the
377+// function address from the vtable if a virtual function is being called).
378+// Dlugosz's trick is to make the codeptr point to a probe function which
379+// returns the 'this' pointer that was used.
380+
381+// Define a generic class that uses virtual inheritance.
382+// It has a trival member function that returns the value of the 'this' pointer.
383+struct GenericVirtualClass : virtual public GenericClass
384+{
385+ typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)();
386+ GenericVirtualClass * GetThis() { return this; }
387+};
388+
389+// __virtual_inheritance classes go here
390+template <>
391+struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 2*sizeof(int) >
392+{
393+
394+ template <class X, class XFuncType, class GenericMemFuncType>
395+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
396+ GenericMemFuncType &bound_func) {
397+ union {
398+ XFuncType func;
399+ GenericClass* (X::*ProbeFunc)();
400+ MicrosoftVirtualMFP s;
401+ } u;
402+ u.func = function_to_bind;
403+ bound_func = reinterpret_cast<GenericMemFuncType>(u.s.codeptr);
404+ union {
405+ GenericVirtualClass::ProbePtrType virtfunc;
406+ MicrosoftVirtualMFP s;
407+ } u2;
408+ // Check that the horrible_cast<>s will work
409+ typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)
410+ && sizeof(function_to_bind)==sizeof(u.ProbeFunc)
411+ && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1];
412+ // Unfortunately, taking the address of a MF prevents it from being inlined, so
413+ // this next line can't be completely optimised away by the compiler.
414+ u2.virtfunc = &GenericVirtualClass::GetThis;
415+ u.s.codeptr = u2.s.codeptr;
416+ return (pthis->*u.ProbeFunc)();
417+ }
418+};
419+
420+#if (_MSC_VER <1300)
421+
422+// Nasty hack for Microsoft Visual C++ 6.0
423+// unknown_inheritance classes go here
424+// There is a compiler bug in MSVC6 which generates incorrect code in this case!!
425+template <>
426+struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
427+{
428+ template <class X, class XFuncType, class GenericMemFuncType>
429+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
430+ GenericMemFuncType &bound_func) {
431+ // There is an apalling but obscure compiler bug in MSVC6 and earlier:
432+ // vtable_index and 'vtordisp' are always set to 0 in the
433+ // unknown_inheritance case!
434+ // This means that an incorrect function could be called!!!
435+ // Compiling with the /vmg option leads to potentially incorrect code.
436+ // This is probably the reason that the IDE has a user interface for specifying
437+ // the /vmg option, but it is disabled - you can only specify /vmg on
438+ // the command line. In VC1.5 and earlier, the compiler would ICE if it ever
439+ // encountered this situation.
440+ // It is OK to use the /vmg option if /vmm or /vms is specified.
441+
442+ // Fortunately, the wrong function is only called in very obscure cases.
443+ // It only occurs when a derived class overrides a virtual function declared
444+ // in a virtual base class, and the member function
445+ // points to the *Derived* version of that function. The problem can be
446+ // completely averted in 100% of cases by using the *Base class* for the
447+ // member fpointer. Ie, if you use the base class as an interface, you'll
448+ // stay out of trouble.
449+ // Occasionally, you might want to point directly to a derived class function
450+ // that isn't an override of a base class. In this case, both vtable_index
451+ // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated.
452+ // We can generate correct code in this case. To prevent an incorrect call from
453+ // ever being made, on MSVC6 we generate a warning, and call a function to
454+ // make the program crash instantly.
455+ typedef char ERROR_VC6CompilerBug[-100];
456+ return 0;
457+ }
458+};
459+
460+
461+#else
462+
463+// Nasty hack for Microsoft and Intel (IA32 and Itanium)
464+// unknown_inheritance classes go here
465+// This is probably the ugliest bit of code I've ever written. Look at the casts!
466+// There is a compiler bug in MSVC6 which prevents it from using this code.
467+template <>
468+struct SimplifyMemFunc<SINGLE_MEMFUNCPTR_SIZE + 3*sizeof(int) >
469+{
470+ template <class X, class XFuncType, class GenericMemFuncType>
471+ inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind,
472+ GenericMemFuncType &bound_func) {
473+ // The member function pointer is 16 bytes long. We can't use a normal cast, but
474+ // we can use a union to do the conversion.
475+ union {
476+ XFuncType func;
477+ // In VC++ and ICL, an unknown_inheritance member pointer
478+ // is internally defined as:
479+ struct {
480+ GenericMemFuncType m_funcaddress; // points to the actual member function
481+ int delta; // #bytes to be added to the 'this' pointer
482+ int vtordisp; // #bytes to add to 'this' to find the vtable
483+ int vtable_index; // or 0 if no virtual inheritance
484+ } s;
485+ } u;
486+ // Check that the horrible_cast will work
487+ typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1];
488+ u.func = function_to_bind;
489+ bound_func = u.s.funcaddress;
490+ int virtual_delta = 0;
491+ if (u.s.vtable_index) { // Virtual inheritance is used
492+ // First, get to the vtable.
493+ // It is 'vtordisp' bytes from the start of the class.
494+ const int * vtable = *reinterpret_cast<const int *const*>(
495+ reinterpret_cast<const char *>(pthis) + u.s.vtordisp );
496+
497+ // 'vtable_index' tells us where in the table we should be looking.
498+ virtual_delta = u.s.vtordisp + *reinterpret_cast<const int *>(
499+ reinterpret_cast<const char *>(vtable) + u.s.vtable_index);
500+ }
501+ // The int at 'virtual_delta' gives us the amount to add to 'this'.
502+ // Finally we can add the three components together. Phew!
503+ return reinterpret_cast<GenericClass *>(
504+ reinterpret_cast<char *>(pthis) + u.s.delta + virtual_delta);
505+ };
506+};
507+#endif // MSVC 7 and greater
508+
509+#endif // MS/Intel hacks
510+
511+} // namespace detail
512+
513+////////////////////////////////////////////////////////////////////////////////
514+// Fast Delegates, part 2:
515+//
516+// Define the delegate storage, and cope with static functions
517+//
518+////////////////////////////////////////////////////////////////////////////////
519+
520+// DelegateMemento -- an opaque structure which can hold an arbitary delegate.
521+// It knows nothing about the calling convention or number of arguments used by
522+// the function pointed to.
523+// It supplies comparison operators so that it can be stored in STL collections.
524+// It cannot be set to anything other than null, nor invoked directly:
525+// it must be converted to a specific delegate.
526+
527+// Implementation:
528+// There are two possible implementations: the Safe method and the Evil method.
529+// DelegateMemento - Safe version
530+//
531+// This implementation is standard-compliant, but a bit tricky.
532+// A static function pointer is stored inside the class.
533+// Here are the valid values:
534+// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+
535+// | 0 | 0 | 0 | Empty |
536+// | !=0 |(dontcare)| Invoker | Static function|
537+// | 0 | !=0 | !=0* | Method call |
538+// +--------------------+----------+------------+----------------+
539+// * For Metrowerks, this can be 0. (first virtual function in a
540+// single_inheritance class).
541+// When stored stored inside a specific delegate, the 'dontcare' entries are replaced
542+// with a reference to the delegate itself. This complicates the = and == operators
543+// for the delegate class.
544+
545+// DelegateMemento - Evil version
546+//
547+// For compilers where data pointers are at least as big as code pointers, it is
548+// possible to store the function pointer in the this pointer, using another
549+// horrible_cast. In this case the DelegateMemento implementation is simple:
550+// +--pThis --+-- pMemFunc-+-- Meaning---------------------+
551+// | 0 | 0 | Empty |
552+// | !=0 | !=0* | Static function or method call|
553+// +----------+------------+-------------------------------+
554+// * For Metrowerks, this can be 0. (first virtual function in a
555+// single_inheritance class).
556+// Note that the Sun C++ and MSVC documentation explicitly state that they
557+// support static_cast between void * and function pointers.
558+
559+class DelegateMemento {
560+protected:
561+ // the data is protected, not private, because many
562+ // compilers have problems with template friends.
563+ typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP.
564+ detail::GenericClass *m_pthis;
565+ GenericMemFuncType m_pFunction;
566+
567+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
568+ typedef void (*GenericFuncPtr)(); // arbitrary code pointer
569+ GenericFuncPtr m_pStaticFunction;
570+#endif
571+
572+public:
573+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
574+ DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {};
575+ void clear() {
576+ m_pthis=0; m_pFunction=0; m_pStaticFunction=0;
577+ }
578+#else
579+ DelegateMemento() : m_pthis(0), m_pFunction(0) {};
580+ void clear() { m_pthis=0; m_pFunction=0; }
581+#endif
582+public:
583+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
584+ inline bool IsEqual (const DelegateMemento &x) const{
585+ // We have to cope with the static function pointers as a special case
586+ if (m_pFunction!=x.m_pFunction) return false;
587+ // the static function ptrs must either both be equal, or both be 0.
588+ if (m_pStaticFunction!=x.m_pStaticFunction) return false;
589+ if (m_pStaticFunction!=0) return m_pthis==x.m_pthis;
590+ else return true;
591+ }
592+#else // Evil Method
593+ inline bool IsEqual (const DelegateMemento &x) const{
594+ return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction;
595+ }
596+#endif
597+ // Provide a strict weak ordering for DelegateMementos.
598+ inline bool IsLess(const DelegateMemento &right) const {
599+ // deal with static function pointers first
600+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
601+ if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0)
602+ return m_pStaticFunction < right.m_pStaticFunction;
603+#endif
604+ if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis;
605+ // There are no ordering operators for member function pointers,
606+ // but we can fake one by comparing each byte. The resulting ordering is
607+ // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers.
608+ return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0;
609+
610+ }
611+ // BUGFIX (Mar 2005):
612+ // We can't just compare m_pFunction because on Metrowerks,
613+ // m_pFunction can be zero even if the delegate is not empty!
614+ inline bool operator ! () const // Is it bound to anything?
615+ { return m_pthis==0 && m_pFunction==0; }
616+ inline bool empty() const // Is it bound to anything?
617+ { return m_pthis==0 && m_pFunction==0; }
618+public:
619+ DelegateMemento & operator = (const DelegateMemento &right) {
620+ SetMementoFrom(right);
621+ return *this;
622+ }
623+ inline bool operator <(const DelegateMemento &right) {
624+ return IsLess(right);
625+ }
626+ inline bool operator >(const DelegateMemento &right) {
627+ return right.IsLess(*this);
628+ }
629+ DelegateMemento (const DelegateMemento &right) :
630+ m_pFunction(right.m_pFunction), m_pthis(right.m_pthis)
631+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
632+ , m_pStaticFunction (right.m_pStaticFunction)
633+#endif
634+ {}
635+protected:
636+ void SetMementoFrom(const DelegateMemento &right) {
637+ m_pFunction = right.m_pFunction;
638+ m_pthis = right.m_pthis;
639+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
640+ m_pStaticFunction = right.m_pStaticFunction;
641+#endif
642+ }
643+};
644+
645+
646+// ClosurePtr<>
647+//
648+// A private wrapper class that adds function signatures to DelegateMemento.
649+// It's the class that does most of the actual work.
650+// The signatures are specified by:
651+// GenericMemFunc: must be a type of GenericClass member function pointer.
652+// StaticFuncPtr: must be a type of function pointer with the same signature
653+// as GenericMemFunc.
654+// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6
655+// where it never returns void (returns DefaultVoid instead).
656+
657+// An outer class, FastDelegateN<>, handles the invoking and creates the
658+// necessary typedefs.
659+// This class does everything else.
660+
661+namespace detail {
662+
663+template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr>
664+class ClosurePtr : public DelegateMemento {
665+public:
666+ // These functions are for setting the delegate to a member function.
667+
668+ // Here's the clever bit: we convert an arbitrary member function into a
669+ // standard form. XMemFunc should be a member function of class X, but I can't
670+ // enforce that here. It needs to be enforced by the wrapper class.
671+ template < class X, class XMemFunc >
672+ inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) {
673+ m_pthis = SimplifyMemFunc< sizeof(function_to_bind) >
674+ ::Convert(pthis, function_to_bind, m_pFunction);
675+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
676+ m_pStaticFunction = 0;
677+#endif
678+ }
679+ // For const member functions, we only need a const class pointer.
680+ // Since we know that the member function is const, it's safe to
681+ // remove the const qualifier from the 'this' pointer with a const_cast.
682+ // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name.
683+ template < class X, class XMemFunc>
684+ inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) {
685+ m_pthis= SimplifyMemFunc< sizeof(function_to_bind) >
686+ ::Convert(const_cast<X*>(pthis), function_to_bind, m_pFunction);
687+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
688+ m_pStaticFunction = 0;
689+#endif
690+ }
691+#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates
692+ template < class X, class XMemFunc>
693+ inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) {
694+ bindconstmemfunc(pthis, function_to_bind);
695+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
696+ m_pStaticFunction = 0;
697+#endif
698+ }
699+#endif
700+ // These functions are required for invoking the stored function
701+ inline GenericClass *GetClosureThis() const { return m_pthis; }
702+ inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast<GenericMemFunc>(m_pFunction); }
703+
704+// There are a few ways of dealing with static function pointers.
705+// There's a standard-compliant, but tricky method.
706+// There's also a straightforward hack, that won't work on DOS compilers using the
707+// medium memory model. It's so evil that I can't recommend it, but I've
708+// implemented it anyway because it produces very nice asm code.
709+
710+#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
711+
712+// ClosurePtr<> - Safe version
713+//
714+// This implementation is standard-compliant, but a bit tricky.
715+// I store the function pointer inside the class, and the delegate then
716+// points to itself. Whenever the delegate is copied, these self-references
717+// must be transformed, and this complicates the = and == operators.
718+public:
719+ // The next two functions are for operator ==, =, and the copy constructor.
720+ // We may need to convert the m_pthis pointers, so that
721+ // they remain as self-references.
722+ template< class DerivedClass >
723+ inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) {
724+ SetMementoFrom(x);
725+ if (m_pStaticFunction!=0) {
726+ // transform self references...
727+ m_pthis=reinterpret_cast<GenericClass *>(pParent);
728+ }
729+ }
730+ // For static functions, the 'static_function_invoker' class in the parent
731+ // will be called. The parent then needs to call GetStaticFunction() to find out
732+ // the actual function to invoke.
733+ template < class DerivedClass, class ParentInvokerSig >
734+ inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker,
735+ StaticFuncPtr function_to_bind ) {
736+ if (function_to_bind==0) { // cope with assignment to 0
737+ m_pFunction=0;
738+ } else {
739+ bindmemfunc(pParent, static_function_invoker);
740+ }
741+ m_pStaticFunction=reinterpret_cast<GenericFuncPtr>(function_to_bind);
742+ }
743+ inline UnvoidStaticFuncPtr GetStaticFunction() const {
744+ return reinterpret_cast<UnvoidStaticFuncPtr>(m_pStaticFunction);
745+ }
746+#else
747+
748+// ClosurePtr<> - Evil version
749+//
750+// For compilers where data pointers are at least as big as code pointers, it is
751+// possible to store the function pointer in the this pointer, using another
752+// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and
753+// speeds up comparison and assignment. If C++ provided direct language support
754+// for delegates, they would produce asm code that was almost identical to this.
755+// Note that the Sun C++ and MSVC documentation explicitly state that they
756+// support static_cast between void * and function pointers.
757+
758+ template< class DerivedClass >
759+ inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) {
760+ SetMementoFrom(right);
761+ }
762+ // For static functions, the 'static_function_invoker' class in the parent
763+ // will be called. The parent then needs to call GetStaticFunction() to find out
764+ // the actual function to invoke.
765+ // ******** EVIL, EVIL CODE! *******
766+ template < class DerivedClass, class ParentInvokerSig>
767+ inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker,
768+ StaticFuncPtr function_to_bind) {
769+ if (function_to_bind==0) { // cope with assignment to 0
770+ m_pFunction=0;
771+ } else {
772+ // We'll be ignoring the 'this' pointer, but we need to make sure we pass
773+ // a valid value to bindmemfunc().
774+ bindmemfunc(pParent, static_function_invoker);
775+ }
776+
777+ // WARNING! Evil hack. We store the function in the 'this' pointer!
778+ // Ensure that there's a compilation failure if function pointers
779+ // and data pointers have different sizes.
780+ // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
781+ typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1];
782+ m_pthis = horrible_cast<GenericClass *>(function_to_bind);
783+ // MSVC, SunC++ and DMC accept the following (non-standard) code:
784+// m_pthis = static_cast<GenericClass *>(static_cast<void *>(function_to_bind));
785+ // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long
786+// m_pthis = reinterpret_cast<GenericClass *>(reinterpret_cast<long>(function_to_bind));
787+ }
788+ // ******** EVIL, EVIL CODE! *******
789+ // This function will be called with an invalid 'this' pointer!!
790+ // We're just returning the 'this' pointer, converted into
791+ // a function pointer!
792+ inline UnvoidStaticFuncPtr GetStaticFunction() const {
793+ // Ensure that there's a compilation failure if function pointers
794+ // and data pointers have different sizes.
795+ // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK.
796+ typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1];
797+ return horrible_cast<UnvoidStaticFuncPtr>(this);
798+ }
799+#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK)
800+
801+ // Does the closure contain this static function?
802+ inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){
803+ if (funcptr==0) return empty();
804+ // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary
805+ // value that is not equal to any valid function pointer.
806+ else return funcptr==reinterpret_cast<StaticFuncPtr>(GetStaticFunction());
807+ }
808+};
809+
810+
811+} // namespace detail
812+
813+////////////////////////////////////////////////////////////////////////////////
814+// Fast Delegates, part 3:
815+//
816+// Wrapper classes to ensure type safety
817+//
818+////////////////////////////////////////////////////////////////////////////////
819+
820+
821+// Once we have the member function conversion templates, it's easy to make the
822+// wrapper classes. So that they will work with as many compilers as possible,
823+// the classes are of the form
824+// FastDelegate3<int, char *, double>
825+// They can cope with any combination of parameters. The max number of parameters
826+// allowed is 8, but it is trivial to increase this limit.
827+// Note that we need to treat const member functions seperately.
828+// All this class does is to enforce type safety, and invoke the delegate with
829+// the correct list of parameters.
830+
831+// Because of the weird rule about the class of derived member function pointers,
832+// you sometimes need to apply a downcast to the 'this' pointer.
833+// This is the reason for the use of "implicit_cast<X*>(pthis)" in the code below.
834+// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction,
835+// without this trick you'd need to write:
836+// MyDelegate(static_cast<CBaseClass *>(&d), &CDerivedClass::SimpleVirtualFunction);
837+// but with the trick you can write
838+// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction);
839+
840+// RetType is the type the compiler uses in compiling the template. For VC6,
841+// it cannot be void. DesiredRetType is the real type which is returned from
842+// all of the functions. It can be void.
843+
844+// Implicit conversion to "bool" is achieved using the safe_bool idiom,
845+// using member data pointers (MDP). This allows "if (dg)..." syntax
846+// Because some compilers (eg codeplay) don't have a unique value for a zero
847+// MDP, an extra padding member is added to the SafeBool struct.
848+// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so
849+// in that case the static function constructor is not made explicit; this
850+// allows "if (dg==0) ..." to compile.
851+
852+//N=0
853+template<class RetType=detail::DefaultVoid>
854+class FastDelegate0 {
855+private:
856+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
857+ typedef DesiredRetType (*StaticFunctionPtr)();
858+ typedef RetType (*UnvoidStaticFunctionPtr)();
859+ typedef RetType (detail::GenericClass::*GenericMemFn)();
860+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
861+ ClosureType m_Closure;
862+public:
863+ // Typedefs to aid generic programming
864+ typedef FastDelegate0 type;
865+
866+ // Construction and comparison functions
867+ FastDelegate0() { clear(); }
868+ FastDelegate0(const FastDelegate0 &x) {
869+ m_Closure.CopyFrom(this, x.m_Closure); }
870+ void operator = (const FastDelegate0 &x) {
871+ m_Closure.CopyFrom(this, x.m_Closure); }
872+ bool operator ==(const FastDelegate0 &x) const {
873+ return m_Closure.IsEqual(x.m_Closure); }
874+ bool operator !=(const FastDelegate0 &x) const {
875+ return !m_Closure.IsEqual(x.m_Closure); }
876+ bool operator <(const FastDelegate0 &x) const {
877+ return m_Closure.IsLess(x.m_Closure); }
878+ bool operator >(const FastDelegate0 &x) const {
879+ return x.m_Closure.IsLess(m_Closure); }
880+ // Binding to non-const member functions
881+ template < class X, class Y >
882+ FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) {
883+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
884+ template < class X, class Y >
885+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) {
886+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
887+ // Binding to const member functions.
888+ template < class X, class Y >
889+ FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
890+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind); }
891+ template < class X, class Y >
892+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) {
893+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
894+ // Static functions. We convert them into a member function call.
895+ // This constructor also provides implicit conversion
896+ FastDelegate0(DesiredRetType (*function_to_bind)() ) {
897+ bind(function_to_bind); }
898+ // for efficiency, prevent creation of a temporary
899+ void operator = (DesiredRetType (*function_to_bind)() ) {
900+ bind(function_to_bind); }
901+ inline void bind(DesiredRetType (*function_to_bind)()) {
902+ m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction,
903+ function_to_bind); }
904+ // Invoke the delegate
905+ RetType operator() () const {
906+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); }
907+ // Implicit conversion to "bool" using the safe_bool idiom
908+private:
909+ typedef struct SafeBoolStruct {
910+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
911+ StaticFunctionPtr m_nonzero;
912+ } UselessTypedef;
913+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
914+public:
915+ operator unspecified_bool_type() const {
916+ return empty()? 0: &SafeBoolStruct::m_nonzero;
917+ }
918+ // necessary to allow ==0 to work despite the safe_bool idiom
919+ inline bool operator==(StaticFunctionPtr funcptr) {
920+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
921+ inline bool operator!=(StaticFunctionPtr funcptr) {
922+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
923+ inline bool operator ! () const { // Is it bound to anything?
924+ return !m_Closure; }
925+ inline bool empty() const {
926+ return !m_Closure; }
927+ void clear() { m_Closure.clear();}
928+ // Conversion to and from the DelegateMemento storage class
929+ const DelegateMemento & GetMemento() { return m_Closure; }
930+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
931+
932+private: // Invoker for static functions
933+ RetType InvokeStaticFunction() const {
934+ return (*(m_Closure.GetStaticFunction()))(); }
935+};
936+
937+//N=1
938+template<class Param1, class RetType=detail::DefaultVoid>
939+class FastDelegate1 {
940+private:
941+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
942+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1);
943+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1);
944+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1);
945+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
946+ ClosureType m_Closure;
947+public:
948+ // Typedefs to aid generic programming
949+ typedef FastDelegate1 type;
950+
951+ // Construction and comparison functions
952+ FastDelegate1() { clear(); }
953+ FastDelegate1(const FastDelegate1 &x) {
954+ m_Closure.CopyFrom(this, x.m_Closure); }
955+ void operator = (const FastDelegate1 &x) {
956+ m_Closure.CopyFrom(this, x.m_Closure); }
957+ bool operator ==(const FastDelegate1 &x) const {
958+ return m_Closure.IsEqual(x.m_Closure); }
959+ bool operator !=(const FastDelegate1 &x) const {
960+ return !m_Closure.IsEqual(x.m_Closure); }
961+ bool operator <(const FastDelegate1 &x) const {
962+ return m_Closure.IsLess(x.m_Closure); }
963+ bool operator >(const FastDelegate1 &x) const {
964+ return x.m_Closure.IsLess(m_Closure); }
965+ // Binding to non-const member functions
966+ template < class X, class Y >
967+ FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) {
968+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
969+ template < class X, class Y >
970+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) {
971+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
972+ // Binding to const member functions.
973+ template < class X, class Y >
974+ FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
975+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind); }
976+ template < class X, class Y >
977+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) {
978+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
979+ // Static functions. We convert them into a member function call.
980+ // This constructor also provides implicit conversion
981+ FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) {
982+ bind(function_to_bind); }
983+ // for efficiency, prevent creation of a temporary
984+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) {
985+ bind(function_to_bind); }
986+ inline void bind(DesiredRetType (*function_to_bind)(Param1 p1)) {
987+ m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction,
988+ function_to_bind); }
989+ // Invoke the delegate
990+ RetType operator() (Param1 p1) const {
991+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); }
992+ // Implicit conversion to "bool" using the safe_bool idiom
993+private:
994+ typedef struct SafeBoolStruct {
995+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
996+ StaticFunctionPtr m_nonzero;
997+ } UselessTypedef;
998+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
999+public:
1000+ operator unspecified_bool_type() const {
1001+ return empty()? 0: &SafeBoolStruct::m_nonzero;
1002+ }
1003+ // necessary to allow ==0 to work despite the safe_bool idiom
1004+ inline bool operator==(StaticFunctionPtr funcptr) {
1005+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1006+ inline bool operator!=(StaticFunctionPtr funcptr) {
1007+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1008+ inline bool operator ! () const { // Is it bound to anything?
1009+ return !m_Closure; }
1010+ inline bool empty() const {
1011+ return !m_Closure; }
1012+ void clear() { m_Closure.clear();}
1013+ // Conversion to and from the DelegateMemento storage class
1014+ const DelegateMemento & GetMemento() { return m_Closure; }
1015+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1016+
1017+private: // Invoker for static functions
1018+ RetType InvokeStaticFunction(Param1 p1) const {
1019+ return (*(m_Closure.GetStaticFunction()))(p1); }
1020+};
1021+
1022+//N=2
1023+template<class Param1, class Param2, class RetType=detail::DefaultVoid>
1024+class FastDelegate2 {
1025+private:
1026+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1027+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2);
1028+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2);
1029+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2);
1030+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1031+ ClosureType m_Closure;
1032+public:
1033+ // Typedefs to aid generic programming
1034+ typedef FastDelegate2 type;
1035+
1036+ // Construction and comparison functions
1037+ FastDelegate2() { clear(); }
1038+ FastDelegate2(const FastDelegate2 &x) {
1039+ m_Closure.CopyFrom(this, x.m_Closure); }
1040+ void operator = (const FastDelegate2 &x) {
1041+ m_Closure.CopyFrom(this, x.m_Closure); }
1042+ bool operator ==(const FastDelegate2 &x) const {
1043+ return m_Closure.IsEqual(x.m_Closure); }
1044+ bool operator !=(const FastDelegate2 &x) const {
1045+ return !m_Closure.IsEqual(x.m_Closure); }
1046+ bool operator <(const FastDelegate2 &x) const {
1047+ return m_Closure.IsLess(x.m_Closure); }
1048+ bool operator >(const FastDelegate2 &x) const {
1049+ return x.m_Closure.IsLess(m_Closure); }
1050+ // Binding to non-const member functions
1051+ template < class X, class Y >
1052+ FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) {
1053+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1054+ template < class X, class Y >
1055+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) {
1056+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1057+ // Binding to const member functions.
1058+ template < class X, class Y >
1059+ FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
1060+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind); }
1061+ template < class X, class Y >
1062+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) {
1063+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1064+ // Static functions. We convert them into a member function call.
1065+ // This constructor also provides implicit conversion
1066+ FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
1067+ bind(function_to_bind); }
1068+ // for efficiency, prevent creation of a temporary
1069+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) {
1070+ bind(function_to_bind); }
1071+ inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) {
1072+ m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction,
1073+ function_to_bind); }
1074+ // Invoke the delegate
1075+ RetType operator() (Param1 p1, Param2 p2) const {
1076+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); }
1077+ // Implicit conversion to "bool" using the safe_bool idiom
1078+private:
1079+ typedef struct SafeBoolStruct {
1080+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
1081+ StaticFunctionPtr m_nonzero;
1082+ } UselessTypedef;
1083+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1084+public:
1085+ operator unspecified_bool_type() const {
1086+ return empty()? 0: &SafeBoolStruct::m_nonzero;
1087+ }
1088+ // necessary to allow ==0 to work despite the safe_bool idiom
1089+ inline bool operator==(StaticFunctionPtr funcptr) {
1090+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1091+ inline bool operator!=(StaticFunctionPtr funcptr) {
1092+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1093+ inline bool operator ! () const { // Is it bound to anything?
1094+ return !m_Closure; }
1095+ inline bool empty() const {
1096+ return !m_Closure; }
1097+ void clear() { m_Closure.clear();}
1098+ // Conversion to and from the DelegateMemento storage class
1099+ const DelegateMemento & GetMemento() { return m_Closure; }
1100+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1101+
1102+private: // Invoker for static functions
1103+ RetType InvokeStaticFunction(Param1 p1, Param2 p2) const {
1104+ return (*(m_Closure.GetStaticFunction()))(p1, p2); }
1105+};
1106+
1107+//N=3
1108+template<class Param1, class Param2, class Param3, class RetType=detail::DefaultVoid>
1109+class FastDelegate3 {
1110+private:
1111+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1112+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
1113+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3);
1114+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3);
1115+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1116+ ClosureType m_Closure;
1117+public:
1118+ // Typedefs to aid generic programming
1119+ typedef FastDelegate3 type;
1120+
1121+ // Construction and comparison functions
1122+ FastDelegate3() { clear(); }
1123+ FastDelegate3(const FastDelegate3 &x) {
1124+ m_Closure.CopyFrom(this, x.m_Closure); }
1125+ void operator = (const FastDelegate3 &x) {
1126+ m_Closure.CopyFrom(this, x.m_Closure); }
1127+ bool operator ==(const FastDelegate3 &x) const {
1128+ return m_Closure.IsEqual(x.m_Closure); }
1129+ bool operator !=(const FastDelegate3 &x) const {
1130+ return !m_Closure.IsEqual(x.m_Closure); }
1131+ bool operator <(const FastDelegate3 &x) const {
1132+ return m_Closure.IsLess(x.m_Closure); }
1133+ bool operator >(const FastDelegate3 &x) const {
1134+ return x.m_Closure.IsLess(m_Closure); }
1135+ // Binding to non-const member functions
1136+ template < class X, class Y >
1137+ FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
1138+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1139+ template < class X, class Y >
1140+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
1141+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1142+ // Binding to const member functions.
1143+ template < class X, class Y >
1144+ FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
1145+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind); }
1146+ template < class X, class Y >
1147+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) {
1148+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1149+ // Static functions. We convert them into a member function call.
1150+ // This constructor also provides implicit conversion
1151+ FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
1152+ bind(function_to_bind); }
1153+ // for efficiency, prevent creation of a temporary
1154+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) {
1155+ bind(function_to_bind); }
1156+ inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) {
1157+ m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction,
1158+ function_to_bind); }
1159+ // Invoke the delegate
1160+ RetType operator() (Param1 p1, Param2 p2, Param3 p3) const {
1161+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); }
1162+ // Implicit conversion to "bool" using the safe_bool idiom
1163+private:
1164+ typedef struct SafeBoolStruct {
1165+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
1166+ StaticFunctionPtr m_nonzero;
1167+ } UselessTypedef;
1168+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1169+public:
1170+ operator unspecified_bool_type() const {
1171+ return empty()? 0: &SafeBoolStruct::m_nonzero;
1172+ }
1173+ // necessary to allow ==0 to work despite the safe_bool idiom
1174+ inline bool operator==(StaticFunctionPtr funcptr) {
1175+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1176+ inline bool operator!=(StaticFunctionPtr funcptr) {
1177+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1178+ inline bool operator ! () const { // Is it bound to anything?
1179+ return !m_Closure; }
1180+ inline bool empty() const {
1181+ return !m_Closure; }
1182+ void clear() { m_Closure.clear();}
1183+ // Conversion to and from the DelegateMemento storage class
1184+ const DelegateMemento & GetMemento() { return m_Closure; }
1185+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1186+
1187+private: // Invoker for static functions
1188+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const {
1189+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); }
1190+};
1191+
1192+//N=4
1193+template<class Param1, class Param2, class Param3, class Param4, class RetType=detail::DefaultVoid>
1194+class FastDelegate4 {
1195+private:
1196+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1197+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
1198+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
1199+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4);
1200+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1201+ ClosureType m_Closure;
1202+public:
1203+ // Typedefs to aid generic programming
1204+ typedef FastDelegate4 type;
1205+
1206+ // Construction and comparison functions
1207+ FastDelegate4() { clear(); }
1208+ FastDelegate4(const FastDelegate4 &x) {
1209+ m_Closure.CopyFrom(this, x.m_Closure); }
1210+ void operator = (const FastDelegate4 &x) {
1211+ m_Closure.CopyFrom(this, x.m_Closure); }
1212+ bool operator ==(const FastDelegate4 &x) const {
1213+ return m_Closure.IsEqual(x.m_Closure); }
1214+ bool operator !=(const FastDelegate4 &x) const {
1215+ return !m_Closure.IsEqual(x.m_Closure); }
1216+ bool operator <(const FastDelegate4 &x) const {
1217+ return m_Closure.IsLess(x.m_Closure); }
1218+ bool operator >(const FastDelegate4 &x) const {
1219+ return x.m_Closure.IsLess(m_Closure); }
1220+ // Binding to non-const member functions
1221+ template < class X, class Y >
1222+ FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
1223+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1224+ template < class X, class Y >
1225+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
1226+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1227+ // Binding to const member functions.
1228+ template < class X, class Y >
1229+ FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
1230+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind); }
1231+ template < class X, class Y >
1232+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
1233+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1234+ // Static functions. We convert them into a member function call.
1235+ // This constructor also provides implicit conversion
1236+ FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
1237+ bind(function_to_bind); }
1238+ // for efficiency, prevent creation of a temporary
1239+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) {
1240+ bind(function_to_bind); }
1241+ inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
1242+ m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction,
1243+ function_to_bind); }
1244+ // Invoke the delegate
1245+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
1246+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); }
1247+ // Implicit conversion to "bool" using the safe_bool idiom
1248+private:
1249+ typedef struct SafeBoolStruct {
1250+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
1251+ StaticFunctionPtr m_nonzero;
1252+ } UselessTypedef;
1253+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1254+public:
1255+ operator unspecified_bool_type() const {
1256+ return empty()? 0: &SafeBoolStruct::m_nonzero;
1257+ }
1258+ // necessary to allow ==0 to work despite the safe_bool idiom
1259+ inline bool operator==(StaticFunctionPtr funcptr) {
1260+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1261+ inline bool operator!=(StaticFunctionPtr funcptr) {
1262+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1263+ inline bool operator ! () const { // Is it bound to anything?
1264+ return !m_Closure; }
1265+ inline bool empty() const {
1266+ return !m_Closure; }
1267+ void clear() { m_Closure.clear();}
1268+ // Conversion to and from the DelegateMemento storage class
1269+ const DelegateMemento & GetMemento() { return m_Closure; }
1270+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1271+
1272+private: // Invoker for static functions
1273+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const {
1274+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); }
1275+};
1276+
1277+//N=5
1278+template<class Param1, class Param2, class Param3, class Param4, class Param5, class RetType=detail::DefaultVoid>
1279+class FastDelegate5 {
1280+private:
1281+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1282+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
1283+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
1284+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5);
1285+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1286+ ClosureType m_Closure;
1287+public:
1288+ // Typedefs to aid generic programming
1289+ typedef FastDelegate5 type;
1290+
1291+ // Construction and comparison functions
1292+ FastDelegate5() { clear(); }
1293+ FastDelegate5(const FastDelegate5 &x) {
1294+ m_Closure.CopyFrom(this, x.m_Closure); }
1295+ void operator = (const FastDelegate5 &x) {
1296+ m_Closure.CopyFrom(this, x.m_Closure); }
1297+ bool operator ==(const FastDelegate5 &x) const {
1298+ return m_Closure.IsEqual(x.m_Closure); }
1299+ bool operator !=(const FastDelegate5 &x) const {
1300+ return !m_Closure.IsEqual(x.m_Closure); }
1301+ bool operator <(const FastDelegate5 &x) const {
1302+ return m_Closure.IsLess(x.m_Closure); }
1303+ bool operator >(const FastDelegate5 &x) const {
1304+ return x.m_Closure.IsLess(m_Closure); }
1305+ // Binding to non-const member functions
1306+ template < class X, class Y >
1307+ FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
1308+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1309+ template < class X, class Y >
1310+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
1311+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1312+ // Binding to const member functions.
1313+ template < class X, class Y >
1314+ FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
1315+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind); }
1316+ template < class X, class Y >
1317+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
1318+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1319+ // Static functions. We convert them into a member function call.
1320+ // This constructor also provides implicit conversion
1321+ FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
1322+ bind(function_to_bind); }
1323+ // for efficiency, prevent creation of a temporary
1324+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) {
1325+ bind(function_to_bind); }
1326+ inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
1327+ m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction,
1328+ function_to_bind); }
1329+ // Invoke the delegate
1330+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
1331+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); }
1332+ // Implicit conversion to "bool" using the safe_bool idiom
1333+private:
1334+ typedef struct SafeBoolStruct {
1335+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
1336+ StaticFunctionPtr m_nonzero;
1337+ } UselessTypedef;
1338+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1339+public:
1340+ operator unspecified_bool_type() const {
1341+ return empty()? 0: &SafeBoolStruct::m_nonzero;
1342+ }
1343+ // necessary to allow ==0 to work despite the safe_bool idiom
1344+ inline bool operator==(StaticFunctionPtr funcptr) {
1345+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1346+ inline bool operator!=(StaticFunctionPtr funcptr) {
1347+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1348+ inline bool operator ! () const { // Is it bound to anything?
1349+ return !m_Closure; }
1350+ inline bool empty() const {
1351+ return !m_Closure; }
1352+ void clear() { m_Closure.clear();}
1353+ // Conversion to and from the DelegateMemento storage class
1354+ const DelegateMemento & GetMemento() { return m_Closure; }
1355+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1356+
1357+private: // Invoker for static functions
1358+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const {
1359+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); }
1360+};
1361+
1362+//N=6
1363+template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType=detail::DefaultVoid>
1364+class FastDelegate6 {
1365+private:
1366+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1367+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
1368+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
1369+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6);
1370+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1371+ ClosureType m_Closure;
1372+public:
1373+ // Typedefs to aid generic programming
1374+ typedef FastDelegate6 type;
1375+
1376+ // Construction and comparison functions
1377+ FastDelegate6() { clear(); }
1378+ FastDelegate6(const FastDelegate6 &x) {
1379+ m_Closure.CopyFrom(this, x.m_Closure); }
1380+ void operator = (const FastDelegate6 &x) {
1381+ m_Closure.CopyFrom(this, x.m_Closure); }
1382+ bool operator ==(const FastDelegate6 &x) const {
1383+ return m_Closure.IsEqual(x.m_Closure); }
1384+ bool operator !=(const FastDelegate6 &x) const {
1385+ return !m_Closure.IsEqual(x.m_Closure); }
1386+ bool operator <(const FastDelegate6 &x) const {
1387+ return m_Closure.IsLess(x.m_Closure); }
1388+ bool operator >(const FastDelegate6 &x) const {
1389+ return x.m_Closure.IsLess(m_Closure); }
1390+ // Binding to non-const member functions
1391+ template < class X, class Y >
1392+ FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
1393+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1394+ template < class X, class Y >
1395+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
1396+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1397+ // Binding to const member functions.
1398+ template < class X, class Y >
1399+ FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
1400+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind); }
1401+ template < class X, class Y >
1402+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
1403+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1404+ // Static functions. We convert them into a member function call.
1405+ // This constructor also provides implicit conversion
1406+ FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
1407+ bind(function_to_bind); }
1408+ // for efficiency, prevent creation of a temporary
1409+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) {
1410+ bind(function_to_bind); }
1411+ inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
1412+ m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction,
1413+ function_to_bind); }
1414+ // Invoke the delegate
1415+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
1416+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); }
1417+ // Implicit conversion to "bool" using the safe_bool idiom
1418+private:
1419+ typedef struct SafeBoolStruct {
1420+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
1421+ StaticFunctionPtr m_nonzero;
1422+ } UselessTypedef;
1423+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1424+public:
1425+ operator unspecified_bool_type() const {
1426+ return empty()? 0: &SafeBoolStruct::m_nonzero;
1427+ }
1428+ // necessary to allow ==0 to work despite the safe_bool idiom
1429+ inline bool operator==(StaticFunctionPtr funcptr) {
1430+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1431+ inline bool operator!=(StaticFunctionPtr funcptr) {
1432+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1433+ inline bool operator ! () const { // Is it bound to anything?
1434+ return !m_Closure; }
1435+ inline bool empty() const {
1436+ return !m_Closure; }
1437+ void clear() { m_Closure.clear();}
1438+ // Conversion to and from the DelegateMemento storage class
1439+ const DelegateMemento & GetMemento() { return m_Closure; }
1440+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1441+
1442+private: // Invoker for static functions
1443+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const {
1444+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); }
1445+};
1446+
1447+//N=7
1448+template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType=detail::DefaultVoid>
1449+class FastDelegate7 {
1450+private:
1451+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1452+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
1453+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
1454+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7);
1455+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1456+ ClosureType m_Closure;
1457+public:
1458+ // Typedefs to aid generic programming
1459+ typedef FastDelegate7 type;
1460+
1461+ // Construction and comparison functions
1462+ FastDelegate7() { clear(); }
1463+ FastDelegate7(const FastDelegate7 &x) {
1464+ m_Closure.CopyFrom(this, x.m_Closure); }
1465+ void operator = (const FastDelegate7 &x) {
1466+ m_Closure.CopyFrom(this, x.m_Closure); }
1467+ bool operator ==(const FastDelegate7 &x) const {
1468+ return m_Closure.IsEqual(x.m_Closure); }
1469+ bool operator !=(const FastDelegate7 &x) const {
1470+ return !m_Closure.IsEqual(x.m_Closure); }
1471+ bool operator <(const FastDelegate7 &x) const {
1472+ return m_Closure.IsLess(x.m_Closure); }
1473+ bool operator >(const FastDelegate7 &x) const {
1474+ return x.m_Closure.IsLess(m_Closure); }
1475+ // Binding to non-const member functions
1476+ template < class X, class Y >
1477+ FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
1478+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1479+ template < class X, class Y >
1480+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
1481+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1482+ // Binding to const member functions.
1483+ template < class X, class Y >
1484+ FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) {
1485+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind); }
1486+ template < class X, class Y >
1487+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) {
1488+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1489+ // Static functions. We convert them into a member function call.
1490+ // This constructor also provides implicit conversion
1491+ FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
1492+ bind(function_to_bind); }
1493+ // for efficiency, prevent creation of a temporary
1494+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) {
1495+ bind(function_to_bind); }
1496+ inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
1497+ m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction,
1498+ function_to_bind); }
1499+ // Invoke the delegate
1500+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
1501+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); }
1502+ // Implicit conversion to "bool" using the safe_bool idiom
1503+private:
1504+ typedef struct SafeBoolStruct {
1505+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
1506+ StaticFunctionPtr m_nonzero;
1507+ } UselessTypedef;
1508+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1509+public:
1510+ operator unspecified_bool_type() const {
1511+ return empty()? 0: &SafeBoolStruct::m_nonzero;
1512+ }
1513+ // necessary to allow ==0 to work despite the safe_bool idiom
1514+ inline bool operator==(StaticFunctionPtr funcptr) {
1515+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1516+ inline bool operator!=(StaticFunctionPtr funcptr) {
1517+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1518+ inline bool operator ! () const { // Is it bound to anything?
1519+ return !m_Closure; }
1520+ inline bool empty() const {
1521+ return !m_Closure; }
1522+ void clear() { m_Closure.clear();}
1523+ // Conversion to and from the DelegateMemento storage class
1524+ const DelegateMemento & GetMemento() { return m_Closure; }
1525+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1526+
1527+private: // Invoker for static functions
1528+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const {
1529+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); }
1530+};
1531+
1532+//N=8
1533+template<class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType=detail::DefaultVoid>
1534+class FastDelegate8 {
1535+private:
1536+ typedef typename detail::DefaultVoidToVoid<RetType>::type DesiredRetType;
1537+ typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
1538+ typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
1539+ typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8);
1540+ typedef detail::ClosurePtr<GenericMemFn, StaticFunctionPtr, UnvoidStaticFunctionPtr> ClosureType;
1541+ ClosureType m_Closure;
1542+public:
1543+ // Typedefs to aid generic programming
1544+ typedef FastDelegate8 type;
1545+
1546+ // Construction and comparison functions
1547+ FastDelegate8() { clear(); }
1548+ FastDelegate8(const FastDelegate8 &x) {
1549+ m_Closure.CopyFrom(this, x.m_Closure); }
1550+ void operator = (const FastDelegate8 &x) {
1551+ m_Closure.CopyFrom(this, x.m_Closure); }
1552+ bool operator ==(const FastDelegate8 &x) const {
1553+ return m_Closure.IsEqual(x.m_Closure); }
1554+ bool operator !=(const FastDelegate8 &x) const {
1555+ return !m_Closure.IsEqual(x.m_Closure); }
1556+ bool operator <(const FastDelegate8 &x) const {
1557+ return m_Closure.IsLess(x.m_Closure); }
1558+ bool operator >(const FastDelegate8 &x) const {
1559+ return x.m_Closure.IsLess(m_Closure); }
1560+ // Binding to non-const member functions
1561+ template < class X, class Y >
1562+ FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
1563+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1564+ template < class X, class Y >
1565+ inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) {
1566+ m_Closure.bindmemfunc(detail::implicit_cast<X*>(pthis), function_to_bind); }
1567+ // Binding to const member functions.
1568+ template < class X, class Y >
1569+ FastDelegate8(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) {
1570+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X*>(pthis), function_to_bind); }
1571+ template < class X, class Y >
1572+ inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) {
1573+ m_Closure.bindconstmemfunc(detail::implicit_cast<const X *>(pthis), function_to_bind); }
1574+ // Static functions. We convert them into a member function call.
1575+ // This constructor also provides implicit conversion
1576+ FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
1577+ bind(function_to_bind); }
1578+ // for efficiency, prevent creation of a temporary
1579+ void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) {
1580+ bind(function_to_bind); }
1581+ inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) {
1582+ m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction,
1583+ function_to_bind); }
1584+ // Invoke the delegate
1585+ RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
1586+ return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); }
1587+ // Implicit conversion to "bool" using the safe_bool idiom
1588+private:
1589+ typedef struct SafeBoolStruct {
1590+ int a_data_pointer_to_this_is_0_on_buggy_compilers;
1591+ StaticFunctionPtr m_nonzero;
1592+ } UselessTypedef;
1593+ typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type;
1594+public:
1595+ operator unspecified_bool_type() const {
1596+ return empty()? 0: &SafeBoolStruct::m_nonzero;
1597+ }
1598+ // necessary to allow ==0 to work despite the safe_bool idiom
1599+ inline bool operator==(StaticFunctionPtr funcptr) {
1600+ return m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1601+ inline bool operator!=(StaticFunctionPtr funcptr) {
1602+ return !m_Closure.IsEqualToStaticFuncPtr(funcptr); }
1603+ inline bool operator ! () const { // Is it bound to anything?
1604+ return !m_Closure; }
1605+ inline bool empty() const {
1606+ return !m_Closure; }
1607+ void clear() { m_Closure.clear();}
1608+ // Conversion to and from the DelegateMemento storage class
1609+ const DelegateMemento & GetMemento() { return m_Closure; }
1610+ void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); }
1611+
1612+private: // Invoker for static functions
1613+ RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const {
1614+ return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); }
1615+};
1616+
1617+
1618+////////////////////////////////////////////////////////////////////////////////
1619+// Fast Delegates, part 4:
1620+//
1621+// FastDelegate<> class (Original author: Jody Hagins)
1622+// Allows boost::function style syntax like:
1623+// FastDelegate< double (int, long) >
1624+// instead of:
1625+// FastDelegate2< int, long, double >
1626+//
1627+////////////////////////////////////////////////////////////////////////////////
1628+
1629+#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
1630+
1631+// Declare FastDelegate as a class template. It will be specialized
1632+// later for all number of arguments.
1633+template <typename Signature>
1634+class FastDelegate;
1635+
1636+//N=0
1637+// Specialization to allow use of
1638+// FastDelegate< R ( ) >
1639+// instead of
1640+// FastDelegate0 < R >
1641+template<typename R>
1642+class FastDelegate< R ( ) >
1643+ // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0
1644+ : public FastDelegate0 < R >
1645+{
1646+public:
1647+ // Make using the base type a bit easier via typedef.
1648+ typedef FastDelegate0 < R > BaseType;
1649+
1650+ // Allow users access to the specific type of this delegate.
1651+ typedef FastDelegate SelfType;
1652+
1653+ // Mimic the base class constructors.
1654+ FastDelegate() : BaseType() { }
1655+
1656+ template < class X, class Y >
1657+ FastDelegate(Y * pthis,
1658+ R (X::* function_to_bind)( ))
1659+ : BaseType(pthis, function_to_bind) { }
1660+
1661+ template < class X, class Y >
1662+ FastDelegate(const Y *pthis,
1663+ R (X::* function_to_bind)( ) const)
1664+ : BaseType(pthis, function_to_bind)
1665+ { }
1666+
1667+ FastDelegate(R (*function_to_bind)( ))
1668+ : BaseType(function_to_bind) { }
1669+ void operator = (const BaseType &x) {
1670+ *static_cast<BaseType*>(this) = x; }
1671+};
1672+
1673+//N=1
1674+// Specialization to allow use of
1675+// FastDelegate< R ( Param1 ) >
1676+// instead of
1677+// FastDelegate1 < Param1, R >
1678+template<typename R, class Param1>
1679+class FastDelegate< R ( Param1 ) >
1680+ // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1
1681+ : public FastDelegate1 < Param1, R >
1682+{
1683+public:
1684+ // Make using the base type a bit easier via typedef.
1685+ typedef FastDelegate1 < Param1, R > BaseType;
1686+
1687+ // Allow users access to the specific type of this delegate.
1688+ typedef FastDelegate SelfType;
1689+
1690+ // Mimic the base class constructors.
1691+ FastDelegate() : BaseType() { }
1692+
1693+ template < class X, class Y >
1694+ FastDelegate(Y * pthis,
1695+ R (X::* function_to_bind)( Param1 p1 ))
1696+ : BaseType(pthis, function_to_bind) { }
1697+
1698+ template < class X, class Y >
1699+ FastDelegate(const Y *pthis,
1700+ R (X::* function_to_bind)( Param1 p1 ) const)
1701+ : BaseType(pthis, function_to_bind)
1702+ { }
1703+
1704+ FastDelegate(R (*function_to_bind)( Param1 p1 ))
1705+ : BaseType(function_to_bind) { }
1706+ void operator = (const BaseType &x) {
1707+ *static_cast<BaseType*>(this) = x; }
1708+};
1709+
1710+//N=2
1711+// Specialization to allow use of
1712+// FastDelegate< R ( Param1, Param2 ) >
1713+// instead of
1714+// FastDelegate2 < Param1, Param2, R >
1715+template<typename R, class Param1, class Param2>
1716+class FastDelegate< R ( Param1, Param2 ) >
1717+ // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2
1718+ : public FastDelegate2 < Param1, Param2, R >
1719+{
1720+public:
1721+ // Make using the base type a bit easier via typedef.
1722+ typedef FastDelegate2 < Param1, Param2, R > BaseType;
1723+
1724+ // Allow users access to the specific type of this delegate.
1725+ typedef FastDelegate SelfType;
1726+
1727+ // Mimic the base class constructors.
1728+ FastDelegate() : BaseType() { }
1729+
1730+ template < class X, class Y >
1731+ FastDelegate(Y * pthis,
1732+ R (X::* function_to_bind)( Param1 p1, Param2 p2 ))
1733+ : BaseType(pthis, function_to_bind) { }
1734+
1735+ template < class X, class Y >
1736+ FastDelegate(const Y *pthis,
1737+ R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const)
1738+ : BaseType(pthis, function_to_bind)
1739+ { }
1740+
1741+ FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 ))
1742+ : BaseType(function_to_bind) { }
1743+ void operator = (const BaseType &x) {
1744+ *static_cast<BaseType*>(this) = x; }
1745+};
1746+
1747+//N=3
1748+// Specialization to allow use of
1749+// FastDelegate< R ( Param1, Param2, Param3 ) >
1750+// instead of
1751+// FastDelegate3 < Param1, Param2, Param3, R >
1752+template<typename R, class Param1, class Param2, class Param3>
1753+class FastDelegate< R ( Param1, Param2, Param3 ) >
1754+ // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3
1755+ : public FastDelegate3 < Param1, Param2, Param3, R >
1756+{
1757+public:
1758+ // Make using the base type a bit easier via typedef.
1759+ typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType;
1760+
1761+ // Allow users access to the specific type of this delegate.
1762+ typedef FastDelegate SelfType;
1763+
1764+ // Mimic the base class constructors.
1765+ FastDelegate() : BaseType() { }
1766+
1767+ template < class X, class Y >
1768+ FastDelegate(Y * pthis,
1769+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
1770+ : BaseType(pthis, function_to_bind) { }
1771+
1772+ template < class X, class Y >
1773+ FastDelegate(const Y *pthis,
1774+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const)
1775+ : BaseType(pthis, function_to_bind)
1776+ { }
1777+
1778+ FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ))
1779+ : BaseType(function_to_bind) { }
1780+ void operator = (const BaseType &x) {
1781+ *static_cast<BaseType*>(this) = x; }
1782+};
1783+
1784+//N=4
1785+// Specialization to allow use of
1786+// FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
1787+// instead of
1788+// FastDelegate4 < Param1, Param2, Param3, Param4, R >
1789+template<typename R, class Param1, class Param2, class Param3, class Param4>
1790+class FastDelegate< R ( Param1, Param2, Param3, Param4 ) >
1791+ // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4
1792+ : public FastDelegate4 < Param1, Param2, Param3, Param4, R >
1793+{
1794+public:
1795+ // Make using the base type a bit easier via typedef.
1796+ typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType;
1797+
1798+ // Allow users access to the specific type of this delegate.
1799+ typedef FastDelegate SelfType;
1800+
1801+ // Mimic the base class constructors.
1802+ FastDelegate() : BaseType() { }
1803+
1804+ template < class X, class Y >
1805+ FastDelegate(Y * pthis,
1806+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
1807+ : BaseType(pthis, function_to_bind) { }
1808+
1809+ template < class X, class Y >
1810+ FastDelegate(const Y *pthis,
1811+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const)
1812+ : BaseType(pthis, function_to_bind)
1813+ { }
1814+
1815+ FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ))
1816+ : BaseType(function_to_bind) { }
1817+ void operator = (const BaseType &x) {
1818+ *static_cast<BaseType*>(this) = x; }
1819+};
1820+
1821+//N=5
1822+// Specialization to allow use of
1823+// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
1824+// instead of
1825+// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
1826+template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5>
1827+class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) >
1828+ // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5
1829+ : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R >
1830+{
1831+public:
1832+ // Make using the base type a bit easier via typedef.
1833+ typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType;
1834+
1835+ // Allow users access to the specific type of this delegate.
1836+ typedef FastDelegate SelfType;
1837+
1838+ // Mimic the base class constructors.
1839+ FastDelegate() : BaseType() { }
1840+
1841+ template < class X, class Y >
1842+ FastDelegate(Y * pthis,
1843+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
1844+ : BaseType(pthis, function_to_bind) { }
1845+
1846+ template < class X, class Y >
1847+ FastDelegate(const Y *pthis,
1848+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const)
1849+ : BaseType(pthis, function_to_bind)
1850+ { }
1851+
1852+ FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ))
1853+ : BaseType(function_to_bind) { }
1854+ void operator = (const BaseType &x) {
1855+ *static_cast<BaseType*>(this) = x; }
1856+};
1857+
1858+//N=6
1859+// Specialization to allow use of
1860+// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
1861+// instead of
1862+// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
1863+template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6>
1864+class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) >
1865+ // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6
1866+ : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R >
1867+{
1868+public:
1869+ // Make using the base type a bit easier via typedef.
1870+ typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType;
1871+
1872+ // Allow users access to the specific type of this delegate.
1873+ typedef FastDelegate SelfType;
1874+
1875+ // Mimic the base class constructors.
1876+ FastDelegate() : BaseType() { }
1877+
1878+ template < class X, class Y >
1879+ FastDelegate(Y * pthis,
1880+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
1881+ : BaseType(pthis, function_to_bind) { }
1882+
1883+ template < class X, class Y >
1884+ FastDelegate(const Y *pthis,
1885+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const)
1886+ : BaseType(pthis, function_to_bind)
1887+ { }
1888+
1889+ FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ))
1890+ : BaseType(function_to_bind) { }
1891+ void operator = (const BaseType &x) {
1892+ *static_cast<BaseType*>(this) = x; }
1893+};
1894+
1895+//N=7
1896+// Specialization to allow use of
1897+// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
1898+// instead of
1899+// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
1900+template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7>
1901+class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >
1902+ // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7
1903+ : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R >
1904+{
1905+public:
1906+ // Make using the base type a bit easier via typedef.
1907+ typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType;
1908+
1909+ // Allow users access to the specific type of this delegate.
1910+ typedef FastDelegate SelfType;
1911+
1912+ // Mimic the base class constructors.
1913+ FastDelegate() : BaseType() { }
1914+
1915+ template < class X, class Y >
1916+ FastDelegate(Y * pthis,
1917+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
1918+ : BaseType(pthis, function_to_bind) { }
1919+
1920+ template < class X, class Y >
1921+ FastDelegate(const Y *pthis,
1922+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const)
1923+ : BaseType(pthis, function_to_bind)
1924+ { }
1925+
1926+ FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ))
1927+ : BaseType(function_to_bind) { }
1928+ void operator = (const BaseType &x) {
1929+ *static_cast<BaseType*>(this) = x; }
1930+};
1931+
1932+//N=8
1933+// Specialization to allow use of
1934+// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
1935+// instead of
1936+// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
1937+template<typename R, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8>
1938+class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >
1939+ // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8
1940+ : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R >
1941+{
1942+public:
1943+ // Make using the base type a bit easier via typedef.
1944+ typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType;
1945+
1946+ // Allow users access to the specific type of this delegate.
1947+ typedef FastDelegate SelfType;
1948+
1949+ // Mimic the base class constructors.
1950+ FastDelegate() : BaseType() { }
1951+
1952+ template < class X, class Y >
1953+ FastDelegate(Y * pthis,
1954+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
1955+ : BaseType(pthis, function_to_bind) { }
1956+
1957+ template < class X, class Y >
1958+ FastDelegate(const Y *pthis,
1959+ R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const)
1960+ : BaseType(pthis, function_to_bind)
1961+ { }
1962+
1963+ FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ))
1964+ : BaseType(function_to_bind) { }
1965+ void operator = (const BaseType &x) {
1966+ *static_cast<BaseType*>(this) = x; }
1967+};
1968+
1969+
1970+#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX
1971+
1972+////////////////////////////////////////////////////////////////////////////////
1973+// Fast Delegates, part 5:
1974+//
1975+// MakeDelegate() helper function
1976+//
1977+// MakeDelegate(&x, &X::func) returns a fastdelegate of the type
1978+// necessary for calling x.func() with the correct number of arguments.
1979+// This makes it possible to eliminate many typedefs from user code.
1980+//
1981+////////////////////////////////////////////////////////////////////////////////
1982+
1983+// Also declare overloads of a MakeDelegate() global function to
1984+// reduce the need for typedefs.
1985+// We need seperate overloads for const and non-const member functions.
1986+// Also, because of the weird rule about the class of derived member function pointers,
1987+// implicit downcasts may need to be applied later to the 'this' pointer.
1988+// That's why two classes (X and Y) appear in the definitions. Y must be implicitly
1989+// castable to X.
1990+
1991+// Workaround for VC6. VC6 needs void return types converted into DefaultVoid.
1992+// GCC 3.2 and later won't compile this unless it's preceded by 'typename',
1993+// but VC6 doesn't allow 'typename' in this context.
1994+// So, I have to use a macro.
1995+
1996+#ifdef FASTDLGT_VC6
1997+#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid<RetType>::type
1998+#else
1999+#define FASTDLGT_RETTYPE RetType
2000+#endif
2001+
2002+//N=0
2003+template <class X, class Y, class RetType>
2004+FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)()) {
2005+ return FastDelegate0<FASTDLGT_RETTYPE>(x, func);
2006+}
2007+
2008+template <class X, class Y, class RetType>
2009+FastDelegate0<FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)() const) {
2010+ return FastDelegate0<FASTDLGT_RETTYPE>(x, func);
2011+}
2012+
2013+//N=1
2014+template <class X, class Y, class Param1, class RetType>
2015+FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1)) {
2016+ return FastDelegate1<Param1, FASTDLGT_RETTYPE>(x, func);
2017+}
2018+
2019+template <class X, class Y, class Param1, class RetType>
2020+FastDelegate1<Param1, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const) {
2021+ return FastDelegate1<Param1, FASTDLGT_RETTYPE>(x, func);
2022+}
2023+
2024+//N=2
2025+template <class X, class Y, class Param1, class Param2, class RetType>
2026+FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2)) {
2027+ return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>(x, func);
2028+}
2029+
2030+template <class X, class Y, class Param1, class Param2, class RetType>
2031+FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const) {
2032+ return FastDelegate2<Param1, Param2, FASTDLGT_RETTYPE>(x, func);
2033+}
2034+
2035+//N=3
2036+template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
2037+FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3)) {
2038+ return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>(x, func);
2039+}
2040+
2041+template <class X, class Y, class Param1, class Param2, class Param3, class RetType>
2042+FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const) {
2043+ return FastDelegate3<Param1, Param2, Param3, FASTDLGT_RETTYPE>(x, func);
2044+}
2045+
2046+//N=4
2047+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
2048+FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) {
2049+ return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>(x, func);
2050+}
2051+
2052+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class RetType>
2053+FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) {
2054+ return FastDelegate4<Param1, Param2, Param3, Param4, FASTDLGT_RETTYPE>(x, func);
2055+}
2056+
2057+//N=5
2058+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
2059+FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) {
2060+ return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>(x, func);
2061+}
2062+
2063+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class RetType>
2064+FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) {
2065+ return FastDelegate5<Param1, Param2, Param3, Param4, Param5, FASTDLGT_RETTYPE>(x, func);
2066+}
2067+
2068+//N=6
2069+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
2070+FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) {
2071+ return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>(x, func);
2072+}
2073+
2074+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class RetType>
2075+FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) {
2076+ return FastDelegate6<Param1, Param2, Param3, Param4, Param5, Param6, FASTDLGT_RETTYPE>(x, func);
2077+}
2078+
2079+//N=7
2080+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
2081+FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) {
2082+ return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>(x, func);
2083+}
2084+
2085+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class RetType>
2086+FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) {
2087+ return FastDelegate7<Param1, Param2, Param3, Param4, Param5, Param6, Param7, FASTDLGT_RETTYPE>(x, func);
2088+}
2089+
2090+//N=8
2091+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
2092+FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) {
2093+ return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>(x, func);
2094+}
2095+
2096+template <class X, class Y, class Param1, class Param2, class Param3, class Param4, class Param5, class Param6, class Param7, class Param8, class RetType>
2097+FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE> MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) {
2098+ return FastDelegate8<Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, FASTDLGT_RETTYPE>(x, func);
2099+}
2100+
2101+
2102+ // clean up after ourselves...
2103+#undef FASTDLGT_RETTYPE
2104+
2105+} // namespace fastdelegate
2106+
2107+#endif // !defined(FASTDELEGATE_H)
2108+
Show on old repository browser