1 /* This file is part of the KDE libraries
2 Copyright (C) 2005, 2006 Ian Reinhart Geiser <geiseri@kde.org>
3 Copyright (C) 2005, 2006 Matt Broadstone <mbroadst@gmail.com>
4 Copyright (C) 2005, 2006 Richard J. Moore <rich@kde.org>
5 Copyright (C) 2005, 2006 Erik L. Bunce <kde@bunce.us>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21 */
22
23 #ifndef VALUE_BINDING_H
24 #define VALUE_BINDING_H
25
26 #include <kjs/object.h>
27 #include <kjs/interpreter.h>
28
29 #include "static_binding.h"
30 #include "pointer.h"
31
32 /**
33 * A simple variant style method.
34 * This will extract the value, cast it to the native type and place it in "value".
35 * Any data that should be returned from this method should be placed into "result";
36 *
37 */
38 #define START_VALUE_METHOD( METHODNAME, TYPE) \
39 KJS::JSValue *METHODNAME( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args ) \
40 { \
41 Q_UNUSED(exec);\
42 Q_UNUSED(self);\
43 Q_UNUSED(args);\
44 KJS::JSValue *result = KJS::jsNull(); \
45 KJSEmbed::ValueBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::ValueBinding>(exec, self ); \
46 if( imp ) \
47 { \
48 TYPE value = imp->value<TYPE>();
49 /**
50 * End a variant method started by START_VALUE_METHOD
51 */
52 #define END_VALUE_METHOD \
53 imp->setValue(value); \
54 } \
55 else { \
56 KJS::throwError(exec, KJS::GeneralError, "Problem in ValueBinding here");\
57 }\
58 return result; \
59 }
60
61 #define KJSO_VALUE_SIMPLE_BINDING_CTOR( NAME, JSNAME, TYPE, BASENAME ) \
62 NAME::NAME(KJS::ExecState *exec, const char* typeName ) \
63 : BASENAME( exec, typeName ) \
64 { \
65 StaticBinding::publish( exec, this, NAME::methods() ); \
66 } \
67 NAME::NAME(KJS::ExecState *exec, const TYPE & value) \
68 : BASENAME( exec, #JSNAME , value ) \
69 { \
70 StaticBinding::publish( exec, this, NAME::methods() ); \
71 }
72
73 #define KJSO_VALUE_DERIVED_BINDING_CTOR( NAME, JSNAME, TYPE, BASENAME ) \
74 NAME::NAME(KJS::ExecState *exec, const char* typeName ) \
75 : BASENAME( exec, typeName ) \
76 { \
77 StaticBinding::publish( exec, this, NAME::methods() ); \
78 } \
79 NAME::NAME(KJS::ExecState *exec, const TYPE & value) \
80 : BASENAME( exec, #JSNAME ) \
81 { \
82 setValue(value); \
83 StaticBinding::publish( exec, this, NAME::methods() ); \
84 }
85
86 namespace KJSEmbed
87 {
88 /**
89 * The Bindings for the KJSEmbed::ValueBinding
90 */
91 class ValueFactory
92 {
93 public:
94 static const Method ValueMethods[];
95 static const Method *methods();
96 };
97
98 /**
99 * Value binding implementation.
100 */
101 class ValueBinding : public ProxyBinding
102 {
103 public:
104 template <typename T>
ValueBinding(KJS::ExecState * exec,const char * typeName,T val)105 ValueBinding(KJS::ExecState *exec, const char *typeName, T val)
106 : ProxyBinding(exec),
107 m_name(typeName)
108 {
109 m_value = new Value<T>(val);
110 StaticBinding::publish(exec, this, ValueFactory::methods());
111 }
112 ValueBinding(KJS::ExecState *exec, const char *typeName);
113 ~ValueBinding() override;
114
115 KJS::UString toString(KJS::ExecState *exec) const override;
className()116 KJS::UString className() const override
117 {
118 return m_name;
119 }
120
121 /**
122 * Returns the stored value.
123 */
124 template< typename T>
value()125 T value() const
126 {
127 const T *ptr = reinterpret_cast<const T *>(m_value->voidStar());
128 if (ptr) {
129 return *ptr;
130 } else {
131 return T();
132 }
133 }
134
135 /**
136 * Set the internal value.
137 */
138 template< typename T>
setValue(const T & val)139 void setValue(const T &val)
140 {
141 delete m_value;
142 m_value = new Value<T>(val);
143 }
144
145 template< typename T>
castValue(ValueBinding * imp)146 static T castValue(ValueBinding *imp)
147 {
148 const T *ptr = reinterpret_cast<const T *>(imp->m_value->voidStar());
149 if (ptr) {
150 return *ptr;
151 } else {
152 return T();
153 }
154 }
155 static const KJS::ClassInfo info;
156
157 private:
classInfo()158 const KJS::ClassInfo *classInfo() const override
159 {
160 return &info;
161 }
162
163 PointerBase *m_value;
164 const char *m_name;
165
166 };
167
168 /**
169 * Extracts a pointer based type from an ObjectBinding object. Care should be taken that this method
170 * is not used with KJSEmbed::ObjectBinding objects because the cast will fail.
171 */
172 template< typename T>
extractValue(KJS::ExecState * exec,KJS::JSValue * arg,const T & defaultValue)173 T extractValue(KJS::ExecState *exec, KJS::JSValue *arg, const T &defaultValue)
174 {
175 if (arg) {
176 KJSEmbed::ValueBinding *imp =
177 KJSEmbed::extractBindingImp<KJSEmbed::ValueBinding>(exec, arg);
178 if (imp) {
179 return ValueBinding::castValue<T>(imp);
180 }
181 }
182 return defaultValue;
183 }
184
185 /**
186 * Extracts a pointer from a KJS::List of KJS::Values. If the argument is out of range the default value
187 * is returned.
188 */
189 template< typename T>
190 T extractValue(KJS::ExecState *exec, const KJS::List &args, int idx, const T &defaultValue = T())
191 {
192 if (args.size() > idx) {
193 return extractValue<T>(exec, args[idx], defaultValue);
194 } else {
195 return defaultValue;
196 }
197 }
198
199 template< typename T>
createValue(KJS::ExecState * exec,const KJS::UString & className,const T & value)200 KJS::JSValue *createValue(KJS::ExecState *exec, const KJS::UString &className, const T &value)
201 {
202 KJS::JSObject *parent = exec->dynamicInterpreter()->globalObject();
203 KJS::JSObject *returnValue = StaticConstructor::construct(exec, parent, className);
204 if (returnValue) {
205 // If it is a value type setValue
206 KJSEmbed::ValueBinding *imp =
207 extractBindingImp<KJSEmbed::ValueBinding>(exec, returnValue);
208 if (imp) {
209 imp->setValue(value);
210 } else {
211 KJS::throwError(exec, KJS::TypeError, toUString(QString("Created failed to cast to %1 failed").arg(toQString(className))));
212 return KJS::jsNull();
213 }
214 } else {
215 KJS::throwError(exec, KJS::TypeError, toUString(QString("Could not construct a %1").arg(toQString(className))));
216 return KJS::jsNull();
217 }
218 return returnValue;
219 }
220 }
221
222 #endif
223
224