michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsQueryFrame_h michael@0: #define nsQueryFrame_h michael@0: michael@0: #include "nscore.h" michael@0: #include "mozilla/Assertions.h" michael@0: #include "mozilla/TypeTraits.h" michael@0: michael@0: // NOTE: the long lines in this file are intentional to make compiler error michael@0: // messages more readable. michael@0: michael@0: #define NS_DECL_QUERYFRAME_TARGET(classname) \ michael@0: static const nsQueryFrame::FrameIID kFrameIID = nsQueryFrame::classname##_id; \ michael@0: typedef classname Has_NS_DECL_QUERYFRAME_TARGET; michael@0: michael@0: #define NS_DECL_QUERYFRAME \ michael@0: virtual void* QueryFrame(FrameIID id); michael@0: michael@0: #define NS_QUERYFRAME_HEAD(class) \ michael@0: void* class::QueryFrame(FrameIID id) { switch (id) { michael@0: michael@0: #define NS_QUERYFRAME_ENTRY(class) \ michael@0: case class::kFrameIID: { \ michael@0: static_assert(mozilla::IsSame::value, \ michael@0: #class " must declare itself as a queryframe target"); \ michael@0: return static_cast(this); \ michael@0: } michael@0: michael@0: #define NS_QUERYFRAME_ENTRY_CONDITIONAL(class, condition) \ michael@0: case class::kFrameIID: \ michael@0: if (condition) { \ michael@0: static_assert(mozilla::IsSame::value, \ michael@0: #class " must declare itself as a queryframe target"); \ michael@0: return static_cast(this); \ michael@0: } \ michael@0: break; michael@0: michael@0: #define NS_QUERYFRAME_TAIL_INHERITING(class) \ michael@0: default: break; \ michael@0: } \ michael@0: return class::QueryFrame(id); \ michael@0: } michael@0: michael@0: #define NS_QUERYFRAME_TAIL_INHERITANCE_ROOT \ michael@0: default: break; \ michael@0: } \ michael@0: MOZ_ASSERT(id != GetFrameId(), \ michael@0: "A frame failed to QueryFrame to its *own type*. " \ michael@0: "It may be missing NS_DECL_QUERYFRAME, or a " \ michael@0: "NS_QUERYFRAME_ENTRY() line with its own type name"); \ michael@0: return nullptr; \ michael@0: } michael@0: michael@0: class nsQueryFrame michael@0: { michael@0: public: michael@0: enum FrameIID { michael@0: #define FRAME_ID(classname) classname##_id, michael@0: #include "nsFrameIdList.h" michael@0: #undef FRAME_ID michael@0: michael@0: // The PresArena implementation uses this bit to distinguish objects michael@0: // allocated by size from objects allocated by type ID (that is, frames michael@0: // using AllocateByFrameID, and other objects using AllocateByObjectID). michael@0: // It should not collide with any frame ID (above) or Object ID (in michael@0: // nsPresArena.h). It is not 0x80000000 to avoid the question of michael@0: // whether enumeration constants are signed. michael@0: NON_FRAME_MARKER = 0x20000000 michael@0: }; michael@0: michael@0: virtual void* QueryFrame(FrameIID id) = 0; michael@0: }; michael@0: michael@0: class do_QueryFrame michael@0: { michael@0: public: michael@0: do_QueryFrame(nsQueryFrame *s) : mRawPtr(s) { } michael@0: michael@0: template michael@0: operator Dest*() { michael@0: static_assert(mozilla::IsSame::value, michael@0: "Dest must declare itself as a queryframe target"); michael@0: if (!mRawPtr) michael@0: return nullptr; michael@0: michael@0: return reinterpret_cast(mRawPtr->QueryFrame(Dest::kFrameIID)); michael@0: } michael@0: michael@0: private: michael@0: nsQueryFrame *mRawPtr; michael@0: }; michael@0: michael@0: #endif // nsQueryFrame_h