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