|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #ifndef nsQueryFrame_h |
|
6 #define nsQueryFrame_h |
|
7 |
|
8 #include "nscore.h" |
|
9 #include "mozilla/Assertions.h" |
|
10 #include "mozilla/TypeTraits.h" |
|
11 |
|
12 // NOTE: the long lines in this file are intentional to make compiler error |
|
13 // messages more readable. |
|
14 |
|
15 #define NS_DECL_QUERYFRAME_TARGET(classname) \ |
|
16 static const nsQueryFrame::FrameIID kFrameIID = nsQueryFrame::classname##_id; \ |
|
17 typedef classname Has_NS_DECL_QUERYFRAME_TARGET; |
|
18 |
|
19 #define NS_DECL_QUERYFRAME \ |
|
20 virtual void* QueryFrame(FrameIID id); |
|
21 |
|
22 #define NS_QUERYFRAME_HEAD(class) \ |
|
23 void* class::QueryFrame(FrameIID id) { switch (id) { |
|
24 |
|
25 #define NS_QUERYFRAME_ENTRY(class) \ |
|
26 case class::kFrameIID: { \ |
|
27 static_assert(mozilla::IsSame<class, class::Has_NS_DECL_QUERYFRAME_TARGET>::value, \ |
|
28 #class " must declare itself as a queryframe target"); \ |
|
29 return static_cast<class*>(this); \ |
|
30 } |
|
31 |
|
32 #define NS_QUERYFRAME_ENTRY_CONDITIONAL(class, condition) \ |
|
33 case class::kFrameIID: \ |
|
34 if (condition) { \ |
|
35 static_assert(mozilla::IsSame<class, class::Has_NS_DECL_QUERYFRAME_TARGET>::value, \ |
|
36 #class " must declare itself as a queryframe target"); \ |
|
37 return static_cast<class*>(this); \ |
|
38 } \ |
|
39 break; |
|
40 |
|
41 #define NS_QUERYFRAME_TAIL_INHERITING(class) \ |
|
42 default: break; \ |
|
43 } \ |
|
44 return class::QueryFrame(id); \ |
|
45 } |
|
46 |
|
47 #define NS_QUERYFRAME_TAIL_INHERITANCE_ROOT \ |
|
48 default: break; \ |
|
49 } \ |
|
50 MOZ_ASSERT(id != GetFrameId(), \ |
|
51 "A frame failed to QueryFrame to its *own type*. " \ |
|
52 "It may be missing NS_DECL_QUERYFRAME, or a " \ |
|
53 "NS_QUERYFRAME_ENTRY() line with its own type name"); \ |
|
54 return nullptr; \ |
|
55 } |
|
56 |
|
57 class nsQueryFrame |
|
58 { |
|
59 public: |
|
60 enum FrameIID { |
|
61 #define FRAME_ID(classname) classname##_id, |
|
62 #include "nsFrameIdList.h" |
|
63 #undef FRAME_ID |
|
64 |
|
65 // The PresArena implementation uses this bit to distinguish objects |
|
66 // allocated by size from objects allocated by type ID (that is, frames |
|
67 // using AllocateByFrameID, and other objects using AllocateByObjectID). |
|
68 // It should not collide with any frame ID (above) or Object ID (in |
|
69 // nsPresArena.h). It is not 0x80000000 to avoid the question of |
|
70 // whether enumeration constants are signed. |
|
71 NON_FRAME_MARKER = 0x20000000 |
|
72 }; |
|
73 |
|
74 virtual void* QueryFrame(FrameIID id) = 0; |
|
75 }; |
|
76 |
|
77 class do_QueryFrame |
|
78 { |
|
79 public: |
|
80 do_QueryFrame(nsQueryFrame *s) : mRawPtr(s) { } |
|
81 |
|
82 template<class Dest> |
|
83 operator Dest*() { |
|
84 static_assert(mozilla::IsSame<Dest, typename Dest::Has_NS_DECL_QUERYFRAME_TARGET>::value, |
|
85 "Dest must declare itself as a queryframe target"); |
|
86 if (!mRawPtr) |
|
87 return nullptr; |
|
88 |
|
89 return reinterpret_cast<Dest*>(mRawPtr->QueryFrame(Dest::kFrameIID)); |
|
90 } |
|
91 |
|
92 private: |
|
93 nsQueryFrame *mRawPtr; |
|
94 }; |
|
95 |
|
96 #endif // nsQueryFrame_h |