File indexing completed on 2024-12-08 12:23:10
0001 /* This file is part of the KDE libraries 0002 Copyright (C) 2005, 2006 Ian Reinhart Geiser <geiseri@kde.org> 0003 Copyright (C) 2005, 2006 Matt Broadstone <mbroadst@gmail.com> 0004 Copyright (C) 2005, 2006 Richard J. Moore <rich@kde.org> 0005 Copyright (C) 2005, 2006 Erik L. Bunce <kde@bunce.us> 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #ifndef VALUE_BINDING_H 0024 #define VALUE_BINDING_H 0025 0026 #include <kjs/object.h> 0027 #include <kjs/interpreter.h> 0028 0029 #include "static_binding.h" 0030 #include "pointer.h" 0031 0032 /** 0033 * A simple variant style method. 0034 * This will extract the value, cast it to the native type and place it in "value". 0035 * Any data that should be returned from this method should be placed into "result"; 0036 * 0037 */ 0038 #define START_VALUE_METHOD( METHODNAME, TYPE) \ 0039 KJS::JSValue *METHODNAME( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args ) \ 0040 { \ 0041 Q_UNUSED(exec);\ 0042 Q_UNUSED(self);\ 0043 Q_UNUSED(args);\ 0044 KJS::JSValue *result = KJS::jsNull(); \ 0045 KJSEmbed::ValueBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::ValueBinding>(exec, self ); \ 0046 if( imp ) \ 0047 { \ 0048 TYPE value = imp->value<TYPE>(); 0049 /** 0050 * End a variant method started by START_VALUE_METHOD 0051 */ 0052 #define END_VALUE_METHOD \ 0053 imp->setValue(value); \ 0054 } \ 0055 else { \ 0056 KJS::throwError(exec, KJS::GeneralError, "Problem in ValueBinding here");\ 0057 }\ 0058 return result; \ 0059 } 0060 0061 #define KJSO_VALUE_SIMPLE_BINDING_CTOR( NAME, JSNAME, TYPE, BASENAME ) \ 0062 NAME::NAME(KJS::ExecState *exec, const char* typeName ) \ 0063 : BASENAME( exec, typeName ) \ 0064 { \ 0065 StaticBinding::publish( exec, this, NAME::methods() ); \ 0066 } \ 0067 NAME::NAME(KJS::ExecState *exec, const TYPE & value) \ 0068 : BASENAME( exec, #JSNAME , value ) \ 0069 { \ 0070 StaticBinding::publish( exec, this, NAME::methods() ); \ 0071 } 0072 0073 #define KJSO_VALUE_DERIVED_BINDING_CTOR( NAME, JSNAME, TYPE, BASENAME ) \ 0074 NAME::NAME(KJS::ExecState *exec, const char* typeName ) \ 0075 : BASENAME( exec, typeName ) \ 0076 { \ 0077 StaticBinding::publish( exec, this, NAME::methods() ); \ 0078 } \ 0079 NAME::NAME(KJS::ExecState *exec, const TYPE & value) \ 0080 : BASENAME( exec, #JSNAME ) \ 0081 { \ 0082 setValue(value); \ 0083 StaticBinding::publish( exec, this, NAME::methods() ); \ 0084 } 0085 0086 namespace KJSEmbed 0087 { 0088 /** 0089 * The Bindings for the KJSEmbed::ValueBinding 0090 */ 0091 class ValueFactory 0092 { 0093 public: 0094 static const Method ValueMethods[]; 0095 static const Method *methods(); 0096 }; 0097 0098 /** 0099 * Value binding implementation. 0100 */ 0101 class ValueBinding : public ProxyBinding 0102 { 0103 public: 0104 template <typename T> 0105 ValueBinding(KJS::ExecState *exec, const char *typeName, T val) 0106 : ProxyBinding(exec), 0107 m_name(typeName) 0108 { 0109 m_value = new Value<T>(val); 0110 StaticBinding::publish(exec, this, ValueFactory::methods()); 0111 } 0112 ValueBinding(KJS::ExecState *exec, const char *typeName); 0113 ~ValueBinding() override; 0114 0115 KJS::UString toString(KJS::ExecState *exec) const override; 0116 KJS::UString className() const override 0117 { 0118 return m_name; 0119 } 0120 0121 /** 0122 * Returns the stored value. 0123 */ 0124 template< typename T> 0125 T value() const 0126 { 0127 const T *ptr = reinterpret_cast<const T *>(m_value->voidStar()); 0128 if (ptr) { 0129 return *ptr; 0130 } else { 0131 return T(); 0132 } 0133 } 0134 0135 /** 0136 * Set the internal value. 0137 */ 0138 template< typename T> 0139 void setValue(const T &val) 0140 { 0141 delete m_value; 0142 m_value = new Value<T>(val); 0143 } 0144 0145 template< typename T> 0146 static T castValue(ValueBinding *imp) 0147 { 0148 const T *ptr = reinterpret_cast<const T *>(imp->m_value->voidStar()); 0149 if (ptr) { 0150 return *ptr; 0151 } else { 0152 return T(); 0153 } 0154 } 0155 static const KJS::ClassInfo info; 0156 0157 private: 0158 const KJS::ClassInfo *classInfo() const override 0159 { 0160 return &info; 0161 } 0162 0163 PointerBase *m_value; 0164 const char *m_name; 0165 0166 }; 0167 0168 /** 0169 * Extracts a pointer based type from an ObjectBinding object. Care should be taken that this method 0170 * is not used with KJSEmbed::ObjectBinding objects because the cast will fail. 0171 */ 0172 template< typename T> 0173 T extractValue(KJS::ExecState *exec, KJS::JSValue *arg, const T &defaultValue) 0174 { 0175 if (arg) { 0176 KJSEmbed::ValueBinding *imp = 0177 KJSEmbed::extractBindingImp<KJSEmbed::ValueBinding>(exec, arg); 0178 if (imp) { 0179 return ValueBinding::castValue<T>(imp); 0180 } 0181 } 0182 return defaultValue; 0183 } 0184 0185 /** 0186 * Extracts a pointer from a KJS::List of KJS::Values. If the argument is out of range the default value 0187 * is returned. 0188 */ 0189 template< typename T> 0190 T extractValue(KJS::ExecState *exec, const KJS::List &args, int idx, const T &defaultValue = T()) 0191 { 0192 if (args.size() > idx) { 0193 return extractValue<T>(exec, args[idx], defaultValue); 0194 } else { 0195 return defaultValue; 0196 } 0197 } 0198 0199 template< typename T> 0200 KJS::JSValue *createValue(KJS::ExecState *exec, const KJS::UString &className, const T &value) 0201 { 0202 KJS::JSObject *parent = exec->dynamicInterpreter()->globalObject(); 0203 KJS::JSObject *returnValue = StaticConstructor::construct(exec, parent, className); 0204 if (returnValue) { 0205 // If it is a value type setValue 0206 KJSEmbed::ValueBinding *imp = 0207 extractBindingImp<KJSEmbed::ValueBinding>(exec, returnValue); 0208 if (imp) { 0209 imp->setValue(value); 0210 } else { 0211 KJS::throwError(exec, KJS::TypeError, toUString(QString("Created failed to cast to %1 failed").arg(toQString(className)))); 0212 return KJS::jsNull(); 0213 } 0214 } else { 0215 KJS::throwError(exec, KJS::TypeError, toUString(QString("Could not construct a %1").arg(toQString(className)))); 0216 return KJS::jsNull(); 0217 } 0218 return returnValue; 0219 } 0220 } 0221 0222 #endif 0223