1 // Copyright 2007, Google Inc.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // Don't actually include dispatcher.h, since this is a template file and will
27 // be included by the .h file. If we do, mkdepend.py explodes in a whirlwind of
28 // angry recursion as it tries to follow the infinite include chain.
30 #include "gears/base/common/js_types.h"
31 #include "gears/base/common/thread_locals.h"
33 // Returns the DispatchId associated with the given string. Used for looking
34 // up methods and properties.
35 inline DispatchId
GetStringIdentifier(const char *str
) {
37 return reinterpret_cast<DispatchId
>(NPN_GetStringIdentifier(str
));
39 // TODO(mpcomplete): Figure out what we need for other ports.
40 // This only works if str is a static string.
41 return reinterpret_cast<DispatchId
>(const_cast<char *>(str
));
46 Dispatcher
<T
>::Dispatcher(ImplClass
*impl
) : impl_(impl
) {
47 // Ensure that property and method mappings are initialized.
48 ThreadLocalVariables
&locals
= GetThreadLocals();
49 if (!locals
.did_init_class
) {
50 locals
.did_init_class
= true;
56 bool Dispatcher
<T
>::HasMethod(DispatchId method_id
) {
57 const IDList
&methods
= GetMethodList();
58 return methods
.find(method_id
) != methods
.end();
62 bool Dispatcher
<T
>::HasPropertyGetter(DispatchId property_id
) {
63 const IDList
&properties
= GetPropertyGetterList();
64 return properties
.find(property_id
) != properties
.end();
68 bool Dispatcher
<T
>::HasPropertySetter(DispatchId property_id
) {
69 const IDList
&properties
= GetPropertySetterList();
70 return properties
.find(property_id
) != properties
.end();
74 bool Dispatcher
<T
>::CallMethod(DispatchId method_id
, JsCallContext
*context
) {
75 const IDList
&methods
= GetMethodList();
76 typename
IDList::const_iterator method
= methods
.find(method_id
);
77 if (method
== methods
.end())
79 ImplCallback callback
= method
->second
;
81 (impl_
->*callback
)(context
);
86 bool Dispatcher
<T
>::GetProperty(DispatchId property_id
,
87 JsCallContext
*context
) {
88 const IDList
&properties
= GetPropertyGetterList();
89 typename
IDList::const_iterator property
= properties
.find(property_id
);
90 if (property
== properties
.end())
92 ImplCallback callback
= property
->second
;
94 (impl_
->*callback
)(context
);
99 bool Dispatcher
<T
>::SetProperty(DispatchId property_id
,
100 JsCallContext
*context
) {
101 const IDList
&properties
= GetPropertySetterList();
102 typename
IDList::const_iterator property
= properties
.find(property_id
);
103 if (property
== properties
.end() || property
->second
== NULL
)
105 ImplCallback callback
= property
->second
;
107 (impl_
->*callback
)(context
);
112 const DispatcherNameList
&Dispatcher
<T
>::GetMemberNames() {
113 return GetThreadLocals().members
;
117 DispatchId Dispatcher
<T
>::GetDispatchId(const std::string
&member_name
) {
118 DispatcherNameList member_names
= GetMemberNames();
119 DispatcherNameList::iterator result
= member_names
.find(member_name
);
120 if (result
!= member_names
.end()) {
121 return result
->second
;
129 void Dispatcher
<T
>::RegisterProperty(const char *name
,
130 ImplCallback getter
, ImplCallback setter
) {
132 DispatchId id
= GetStringIdentifier(name
);
133 GetPropertyGetterList()[id
] = getter
;
134 GetPropertySetterList()[id
] = setter
;
135 GetThreadLocals().members
[name
] = id
;
140 void Dispatcher
<T
>::RegisterMethod(const char *name
, ImplCallback callback
) {
141 DispatchId id
= GetStringIdentifier(name
);
142 GetMethodList()[id
] = callback
;
143 GetThreadLocals().members
[name
] = id
;
148 void Dispatcher
<T
>::DeleteThreadLocals(void *context
) {
149 ThreadLocalVariables
*locals
=
150 reinterpret_cast<ThreadLocalVariables
*>(context
);
156 typename Dispatcher
<T
>::ThreadLocalVariables
&Dispatcher
<T
>::GetThreadLocals() {
157 const std::string
&key
= kThreadLocalsKey
;
158 ThreadLocalVariables
*locals
=
159 reinterpret_cast<ThreadLocalVariables
*>(ThreadLocals::GetValue(key
));
161 locals
= new ThreadLocalVariables
;
162 ThreadLocals::SetValue(key
, locals
, &DeleteThreadLocals
);