GUIで、圧縮設定を調整して結果を確認出来るアプリケーションの作成開始。
@@ -49,8 +49,8 @@ | ||
49 | 49 | |
50 | 50 | int LOCO_IPredictor(int left, int above, int upperLeft) |
51 | 51 | { |
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); | |
54 | 54 | if (upperLeft > maxLeftAbove) { |
55 | 55 | return minLeftAbove; |
56 | 56 | }else if (upperLeft < minLeftAbove) { |
@@ -220,7 +220,7 @@ | ||
220 | 220 | int hists[1024]; |
221 | 221 | int phists[1024]; |
222 | 222 | int mhists[1024]; |
223 | - int zeroRepeatHist[1024*4]; | |
223 | + int zeroRepeatHist[1024*128]; | |
224 | 224 | |
225 | 225 | size_t zeroOneOnlyAreaHist[2]; |
226 | 226 | size_t nonZeroOneOnlyAreaHist[1024]; |
@@ -234,6 +234,13 @@ | ||
234 | 234 | |
235 | 235 | static const size_t DC_BLOCKCOUNT_BORDER = 8192; |
236 | 236 | |
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 | + | |
237 | 244 | size_t compressSub( |
238 | 245 | int* src, |
239 | 246 | const int* pZeroOneInfos, |
@@ -253,7 +260,7 @@ | ||
253 | 260 | |
254 | 261 | int mini = cinfo.mini; |
255 | 262 | 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)); | |
257 | 264 | |
258 | 265 | int* hists = cinfo.hists; |
259 | 266 | int* phists = cinfo.phists; |
@@ -322,7 +329,10 @@ | ||
322 | 329 | } |
323 | 330 | encodedValueSizes[0] = blockCount*blockSize; |
324 | 331 | 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 | |
326 | 336 | values.clear(); |
327 | 337 | int maxV = 0; |
328 | 338 | for (size_t i=0; i<blockCount; ++i) { |
@@ -330,7 +340,7 @@ | ||
330 | 340 | if (!pZeroOneInfos[i]) { |
331 | 341 | for (size_t j=0; j<blockSize; ++j) { |
332 | 342 | int val = src[i*blockSize+j]; |
333 | - maxV = std::max(maxV, val); | |
343 | + maxV = std::max<int>(maxV, val); | |
334 | 344 | cinfo.nonZeroOneOnlyAreaHist[val]++; |
335 | 345 | values.push_back(val); |
336 | 346 | } |
@@ -548,8 +558,8 @@ | ||
548 | 558 | size_t srcCount = blockCount * blockSize; |
549 | 559 | for (size_t j=0; j<srcCount; ++j) { |
550 | 560 | 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); | |
553 | 563 | if (val == 0) { |
554 | 564 | ++zeroRepeat; |
555 | 565 | }else { |
@@ -573,7 +583,7 @@ | ||
573 | 583 | } |
574 | 584 | ci.mini = mini; |
575 | 585 | ci.maxi = maxi; |
576 | - ci.max = std::max(maxi, std::abs(mini)); | |
586 | + ci.max = std::max<int>(maxi, std::abs(mini)); | |
577 | 587 | ci.signFlagsCount = count - oldCount; |
578 | 588 | from += srcCount; |
579 | 589 | } |
@@ -604,7 +614,13 @@ | ||
604 | 614 | progress += compressSub(from, p01, 1<<(i-zeroOneLimit), totalBlockCount, blockSize, dest+progress, destLen-progress, tmp1, tmp2, tmp3, compressInfos[i]); |
605 | 615 | from += totalBlockCount * blockSize; |
606 | 616 | } |
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 | + | |
608 | 624 | return progress; |
609 | 625 | } |
610 | 626 |
@@ -18,6 +18,7 @@ | ||
18 | 18 | return ret; |
19 | 19 | } |
20 | 20 | |
21 | +// quantize blocks... | |
21 | 22 | template <typename T> |
22 | 23 | void encode( |
23 | 24 | Quantizer& quantizer, |
@@ -62,11 +63,11 @@ | ||
62 | 63 | predictor.average = sum / 8; |
63 | 64 | gather(srcLine, inLineOffsetBytes, values); |
64 | 65 | 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); | |
70 | 71 | dct_8x8(tmps, tmps2); |
71 | 72 | quantizer.quantize(tmps); |
72 | 73 | scatter(destLine, outLineOffsetBytes, tmps); |
@@ -98,6 +99,7 @@ | ||
98 | 99 | gather(srcLine, inLineOffsetBytes, values); |
99 | 100 | dct_8x8(values, tmps); |
100 | 101 | quantizer.quantize(values); |
102 | +//values[0][0] = 100; | |
101 | 103 | scatter(destLine, outLineOffsetBytes, values); |
102 | 104 | srcLine += 8; destLine += 8; |
103 | 105 | } |
@@ -36,7 +36,7 @@ | ||
36 | 36 | 27, 29, 31, 33, 36, 38, 40, 42, |
37 | 37 | }; |
38 | 38 | |
39 | -namespace { | |
39 | +namespace impl { | |
40 | 40 | |
41 | 41 | int div(int n, int d) |
42 | 42 | { |
@@ -76,7 +76,7 @@ | ||
76 | 76 | if (useQuantMatrix) { |
77 | 77 | for (size_t i=0; i<8; ++i) { |
78 | 78 | 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]); | |
80 | 80 | dequant8_table[i*8+j] *= QUANT8_INTRA_MATRIX[i][j]; |
81 | 81 | } |
82 | 82 | } |
@@ -98,6 +98,7 @@ | ||
98 | 98 | unsigned char* pSignFlags = &signFlags[0]; |
99 | 99 | size_t signFlagCount = collectInfos(pWork2, totalBlockCount, pSignFlags, compressInfos); |
100 | 100 | |
101 | + // AC係数が0か1だけの場合にそこを纏めて圧縮する。低周波成分はさすがに01だけでは無い事が多い。ただある程度以上の高周波は含んでいないブロックが多い場合がある。 | |
101 | 102 | size_t zeroOneLimit = 2; |
102 | 103 | std::vector<int> zeroOneInfos(totalBlockCount); |
103 | 104 | std::vector<int> allZeroOneInfos(totalBlockCount * 8); |
@@ -60,8 +60,9 @@ | ||
60 | 60 | for (size_t x=0; x<hBlocks; ++x) { |
61 | 61 | |
62 | 62 | gather(srcLine, inLineOffsetBytes, values); |
63 | - | |
63 | + | |
64 | 64 | quantizer.dequantize(values); |
65 | + | |
65 | 66 | idct_8x8(values, tmps); |
66 | 67 | for (size_t i=0; i<8; ++i) { |
67 | 68 | for (size_t j=0; j<8; ++j) { |
@@ -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 | + |
@@ -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 | +}; |
@@ -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 | +}; |
@@ -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 | +} |
@@ -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_ ] |
@@ -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 | +} |
@@ -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 | +} |
@@ -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 | + |
@@ -0,0 +1 @@ | ||
1 | +// ImageCompressionAnalyzer.h |
@@ -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 | +}; |
@@ -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 | + |
@@ -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) |
@@ -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 | + |
@@ -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 | + |
@@ -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 |
@@ -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 | + |