mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Modifications to the var class to make it more javascript-compatible. Changed the handling of array types to be a shared, ref-counted array rather than being copy-by-value. Added an "undefined" type. Updated the native method invocation functions to be static (the old version used class methods) and to provide a 'this' object which may be different from the DynamicObject on which it's being invoked (this is to deal with derived classes)
This commit is contained in:
parent
908754e0ea
commit
03ab2a2c3c
11 changed files with 243 additions and 184 deletions
|
|
@ -1,2 +1,5 @@
|
|||
|
||||
#include "BrowserPluginCharacteristics.h"
|
||||
#define JUCE_MODULE_AVAILABLE_juce_core 1
|
||||
|
||||
#include "BrowserPluginCharacteristics.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -87,13 +87,12 @@ public:
|
|||
class DemoBrowserObject : public DynamicObject
|
||||
{
|
||||
public:
|
||||
DemoBrowserObject (JuceDemoBrowserPlugin* owner_)
|
||||
: owner (owner_)
|
||||
DemoBrowserObject (JuceDemoBrowserPlugin* bp) : owner (bp)
|
||||
{
|
||||
// Add a couple of methods to our object..
|
||||
setMethod ("printText", (var::MethodFunction) &DemoBrowserObject::printText);
|
||||
setMethod ("popUpMessageBox", (var::MethodFunction) &DemoBrowserObject::popUpMessageBox);
|
||||
setMethod ("registerCallbackObject", (var::MethodFunction) &DemoBrowserObject::registerCallbackObject);
|
||||
setMethod ("printText", printText);
|
||||
setMethod ("popUpMessageBox", popUpMessageBox);
|
||||
setMethod ("registerCallbackObject", registerCallbackObject);
|
||||
|
||||
// Add some value properties that the webpage can access
|
||||
setProperty ("property1", "testing testing...");
|
||||
|
|
@ -102,30 +101,33 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
// These methods are called by javascript in the webpage...
|
||||
const var printText (const var* params, int numParams)
|
||||
static var printText (const var::NativeFunctionArgs& args)
|
||||
{
|
||||
if (numParams > 0)
|
||||
owner->textBox.setText (owner->textBox.getText() + "\n" + params[0].toString());
|
||||
if (DemoBrowserObject* b = dynamic_cast<DemoBrowserObject*> (args.thisObject.getObject()))
|
||||
if (args.numArguments > 0)
|
||||
b->owner->textBox.setText (b->owner->textBox.getText() + "\n" + args.arguments[0].toString());
|
||||
|
||||
return "text was printed ok!";
|
||||
}
|
||||
|
||||
const var popUpMessageBox (const var* params, int numParams)
|
||||
static var popUpMessageBox (const var::NativeFunctionArgs& args)
|
||||
{
|
||||
if (numParams > 0)
|
||||
AlertWindow::showMessageBox (AlertWindow::InfoIcon,
|
||||
"A message from the webpage",
|
||||
params[0].toString(),
|
||||
String::empty, owner);
|
||||
return var::null;
|
||||
if (DemoBrowserObject* b = dynamic_cast<DemoBrowserObject*> (args.thisObject.getObject()))
|
||||
if (args.numArguments > 0)
|
||||
AlertWindow::showMessageBox (AlertWindow::InfoIcon,
|
||||
"A message from the webpage",
|
||||
args.arguments[0].toString(),
|
||||
String::empty, b->owner);
|
||||
return var();
|
||||
}
|
||||
|
||||
const var registerCallbackObject (const var* params, int numParams)
|
||||
static var registerCallbackObject (const var::NativeFunctionArgs& args)
|
||||
{
|
||||
if (numParams > 0)
|
||||
owner->setJavascriptObjectFromBrowser (params[0]);
|
||||
if (DemoBrowserObject* b = dynamic_cast<DemoBrowserObject*> (args.thisObject.getObject()))
|
||||
if (args.numArguments > 0)
|
||||
b->owner->setJavascriptObjectFromBrowser (args.arguments[0]);
|
||||
|
||||
return var::null;
|
||||
return var();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
|
||||
#include "AppConfig.h"
|
||||
#include "../../../modules/juce_browser_plugin/juce_browser_plugin.h"
|
||||
#include "../../../modules/juce_browser_plugin_client/juce_browser_plugin.h"
|
||||
|
||||
#if ! DONT_SET_USING_JUCE_NAMESPACE
|
||||
/* If you're not mixing JUCE with other libraries, then this will obviously save
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
|
||||
#include "AppConfig.h"
|
||||
#include "../../../modules/juce_browser_plugin/juce_browser_plugin.cpp"
|
||||
#include "../../../modules/juce_browser_plugin_client/juce_browser_plugin.cpp"
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ public:
|
|||
log ("num IDispatch wrapper objs: " + String (--numDOWID));
|
||||
}
|
||||
|
||||
var getProperty (const Identifier& propertyName) const
|
||||
var getProperty (const Identifier& propertyName) const override
|
||||
{
|
||||
const String nameCopy (propertyName.toString());
|
||||
LPCOLESTR name = nameCopy.toUTF16();
|
||||
|
|
@ -255,7 +255,7 @@ public:
|
|||
return var::null;
|
||||
}
|
||||
|
||||
bool hasProperty (const Identifier& propertyName) const
|
||||
bool hasProperty (const Identifier& propertyName) const override
|
||||
{
|
||||
const String nameCopy (propertyName.toString());
|
||||
LPCOLESTR name = nameCopy.toUTF16();
|
||||
|
|
@ -263,7 +263,7 @@ public:
|
|||
return source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK;
|
||||
}
|
||||
|
||||
void setProperty (const Identifier& propertyName, const var& newValue)
|
||||
void setProperty (const Identifier& propertyName, const var& newValue) override
|
||||
{
|
||||
const String nameCopy (propertyName.toString());
|
||||
LPCOLESTR name = nameCopy.toUTF16();
|
||||
|
|
@ -295,12 +295,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void removeProperty (const Identifier& propertyName)
|
||||
void removeProperty (const Identifier& propertyName) override
|
||||
{
|
||||
setProperty (propertyName, var::null);
|
||||
}
|
||||
|
||||
bool hasMethod (const Identifier& methodName) const
|
||||
bool hasMethod (const Identifier& methodName) const override
|
||||
{
|
||||
const String nameCopy (methodName.toString());
|
||||
LPCOLESTR name = nameCopy.toUTF16();
|
||||
|
|
@ -308,7 +308,7 @@ public:
|
|||
return source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK;
|
||||
}
|
||||
|
||||
var invokeMethod (const Identifier& methodName, const var* parameters, int numParameters)
|
||||
var invokeMethod (Identifier methodName, const var::NativeFunctionArgs& args) override
|
||||
{
|
||||
var returnValue;
|
||||
const String nameCopy (methodName.toString());
|
||||
|
|
@ -317,14 +317,14 @@ public:
|
|||
if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK)
|
||||
{
|
||||
HeapBlock <VARIANT> params;
|
||||
params.calloc (numParameters + 1);
|
||||
params.calloc (args.numArguments + 1);
|
||||
|
||||
for (int i = 0; i < numParameters; ++i)
|
||||
juceVarToVariant (parameters[(numParameters - 1) - i], params[i]);
|
||||
for (int i = 0; i < args.numArguments; ++i)
|
||||
juceVarToVariant (args.arguments[(args.numArguments - 1) - i], params[i]);
|
||||
|
||||
DISPPARAMS dispParams;
|
||||
zerostruct (dispParams);
|
||||
dispParams.cArgs = numParameters;
|
||||
dispParams.cArgs = args.numArguments;
|
||||
dispParams.rgvarg = params;
|
||||
|
||||
EXCEPINFO excepInfo;
|
||||
|
|
|
|||
|
|
@ -616,7 +616,7 @@ public:
|
|||
DBG ("num NP wrapper objs: " + String (--numDOWNP));
|
||||
}
|
||||
|
||||
var getProperty (const var::identifier& propertyName) const
|
||||
var getProperty (const var::identifier& propertyName) const override
|
||||
{
|
||||
NPVariant result;
|
||||
VOID_TO_NPVARIANT (result);
|
||||
|
|
@ -626,7 +626,7 @@ public:
|
|||
return v;
|
||||
}
|
||||
|
||||
bool hasProperty (const var::identifier& propertyName) const
|
||||
bool hasProperty (const var::identifier& propertyName) const override
|
||||
{
|
||||
NPVariant result;
|
||||
VOID_TO_NPVARIANT (result);
|
||||
|
|
@ -635,7 +635,7 @@ public:
|
|||
return hasProp;
|
||||
}
|
||||
|
||||
void setProperty (const var::identifier& propertyName, const var& newValue)
|
||||
void setProperty (const var::identifier& propertyName, const var& newValue) override
|
||||
{
|
||||
NPVariant value;
|
||||
createNPVariantFromValue (npp, value, newValue);
|
||||
|
|
@ -644,40 +644,38 @@ public:
|
|||
browser.releasevariantvalue (&value);
|
||||
}
|
||||
|
||||
void removeProperty (const var::identifier& propertyName)
|
||||
void removeProperty (const var::identifier& propertyName) override
|
||||
{
|
||||
browser.removeproperty (npp, source, getIdentifierFromString (propertyName));
|
||||
}
|
||||
|
||||
bool hasMethod (const var::identifier& methodName) const
|
||||
bool hasMethod (const var::identifier& methodName) const override
|
||||
{
|
||||
return browser.hasmethod (npp, source, getIdentifierFromString (methodName));
|
||||
}
|
||||
|
||||
var invokeMethod (const var::identifier& methodName,
|
||||
const var* parameters,
|
||||
int numParameters)
|
||||
var invokeMethod (Identifier methodName, const var::NativeFunctionArgs& args) override
|
||||
{
|
||||
var returnVal;
|
||||
|
||||
NPVariant result;
|
||||
VOID_TO_NPVARIANT (result);
|
||||
|
||||
if (numParameters > 0)
|
||||
if (args.numArguments > 0)
|
||||
{
|
||||
HeapBlock <NPVariant> params (numParameters);
|
||||
HeapBlock<NPVariant> params (args.numArguments);
|
||||
|
||||
for (int i = 0; i < numParameters; ++i)
|
||||
createNPVariantFromValue (npp, params[i], parameters[i]);
|
||||
for (int i = 0; i < args.numArguments; ++i)
|
||||
createNPVariantFromValue (npp, params[i], args.arguments[i]);
|
||||
|
||||
if (browser.invoke (npp, source, getIdentifierFromString (methodName),
|
||||
params, numParameters, &result))
|
||||
params, args.numArguments, &result))
|
||||
{
|
||||
returnVal = createValueFromNPVariant (npp, result);
|
||||
browser.releasevariantvalue (&result);
|
||||
}
|
||||
|
||||
for (int i = 0; i < numParameters; ++i)
|
||||
for (int i = 0; i < args.numArguments; ++i)
|
||||
browser.releasevariantvalue (¶ms[i]);
|
||||
}
|
||||
else
|
||||
|
|
@ -705,15 +703,14 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
NPObjectWrappingDynamicObject (NPP npp_)
|
||||
: npp (npp_)
|
||||
NPObjectWrappingDynamicObject (NPP n) : npp (n)
|
||||
{
|
||||
DBG ("num Juce wrapper objs: " + String (++numJuceWDO));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool construct (const NPVariant *args, uint32_t argCount, NPVariant *result);
|
||||
void invalidate() {}
|
||||
void invalidate() {}
|
||||
|
||||
bool hasMethod (NPIdentifier name)
|
||||
{
|
||||
|
|
@ -742,7 +739,9 @@ private:
|
|||
for (uint32_t i = 0; i < argCount; ++i)
|
||||
params.params[i] = createValueFromNPVariant (npp, args[i]);
|
||||
|
||||
const var result (o->invokeMethod (methodName, params.params, argCount));
|
||||
|
||||
const var::NativeFunctionArgs argStruct = { object, params.params, (int) argCount };
|
||||
const var result (o->invokeMethod (methodName, argStruct));
|
||||
|
||||
if (out != nullptr)
|
||||
createNPVariantFromValue (npp, *out, result);
|
||||
|
|
|
|||
|
|
@ -60,17 +60,17 @@ bool DynamicObject::hasMethod (const Identifier& methodName) const
|
|||
return getProperty (methodName).isMethod();
|
||||
}
|
||||
|
||||
var DynamicObject::invokeMethod (const Identifier& methodName,
|
||||
const var* parameters,
|
||||
int numParameters)
|
||||
var DynamicObject::invokeMethod (Identifier method, const var::NativeFunctionArgs& args)
|
||||
{
|
||||
return properties [methodName].invokeMethod (this, parameters, numParameters);
|
||||
if (var::NativeFunction function = properties [method].getNativeFunction())
|
||||
return function (args);
|
||||
|
||||
return var();
|
||||
}
|
||||
|
||||
void DynamicObject::setMethod (const Identifier& name,
|
||||
var::MethodFunction methodFunction)
|
||||
void DynamicObject::setMethod (Identifier name, var::NativeFunction function)
|
||||
{
|
||||
properties.set (name, var (methodFunction));
|
||||
properties.set (name, var (function));
|
||||
}
|
||||
|
||||
void DynamicObject::clear()
|
||||
|
|
|
|||
|
|
@ -86,23 +86,16 @@ public:
|
|||
This method is virtual to allow more dynamic invocation to used for objects
|
||||
where the methods may not already be set as properies.
|
||||
*/
|
||||
virtual var invokeMethod (const Identifier& methodName,
|
||||
const var* parameters,
|
||||
int numParameters);
|
||||
virtual var invokeMethod (Identifier methodName,
|
||||
const var::NativeFunctionArgs& args);
|
||||
|
||||
/** Sets up a method.
|
||||
/** Adds a method to the class.
|
||||
|
||||
This is basically the same as calling setProperty (methodName, (var::MethodFunction) myFunction), but
|
||||
This is basically the same as calling setProperty (methodName, (var::NativeFunction) myFunction), but
|
||||
helps to avoid accidentally invoking the wrong type of var constructor. It also makes
|
||||
the code easier to read,
|
||||
|
||||
The compiler will probably force you to use an explicit cast your method to a (var::MethodFunction), e.g.
|
||||
@code
|
||||
setMethod ("doSomething", (var::MethodFunction) &MyClass::doSomething);
|
||||
@endcode
|
||||
*/
|
||||
void setMethod (const Identifier& methodName,
|
||||
var::MethodFunction methodFunction);
|
||||
void setMethod (Identifier methodName, var::NativeFunction function);
|
||||
|
||||
//==============================================================================
|
||||
/** Removes all properties and methods from the object. */
|
||||
|
|
@ -115,6 +108,11 @@ private:
|
|||
//==============================================================================
|
||||
NamedValueSet properties;
|
||||
|
||||
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
|
||||
// These methods have been deprecated - use var::invoke instead
|
||||
virtual void invokeMethod (const Identifier&, const var*, int) {}
|
||||
#endif
|
||||
|
||||
JUCE_LEAK_DETECTOR (DynamicObject)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ enum VariantStreamMarkers
|
|||
varMarker_String = 5,
|
||||
varMarker_Int64 = 6,
|
||||
varMarker_Array = 7,
|
||||
varMarker_Binary = 8
|
||||
varMarker_Binary = 8,
|
||||
varMarker_Undefined = 9
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -55,6 +56,7 @@ public:
|
|||
virtual MemoryBlock* toBinary (const ValueUnion&) const noexcept { return nullptr; }
|
||||
|
||||
virtual bool isVoid() const noexcept { return false; }
|
||||
virtual bool isUndefined() const noexcept { return false; }
|
||||
virtual bool isInt() const noexcept { return false; }
|
||||
virtual bool isInt64() const noexcept { return false; }
|
||||
virtual bool isBool() const noexcept { return false; }
|
||||
|
|
@ -79,10 +81,28 @@ public:
|
|||
static const VariantType_Void instance;
|
||||
|
||||
bool isVoid() const noexcept { return true; }
|
||||
bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept { return otherType.isVoid(); }
|
||||
bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept { return otherType.isVoid() || otherType.isUndefined(); }
|
||||
void writeToStream (const ValueUnion&, OutputStream& output) const { output.writeCompressedInt (0); }
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class var::VariantType_Undefined : public var::VariantType
|
||||
{
|
||||
public:
|
||||
VariantType_Undefined() noexcept {}
|
||||
static const VariantType_Undefined instance;
|
||||
|
||||
bool isUndefined() const noexcept { return true; }
|
||||
String toString (const ValueUnion&) const { return "undefined"; }
|
||||
bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept { return otherType.isVoid() || otherType.isUndefined(); }
|
||||
|
||||
void writeToStream (const ValueUnion&, OutputStream& output) const
|
||||
{
|
||||
output.writeCompressedInt (1);
|
||||
output.writeByte (varMarker_Undefined);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class var::VariantType_Int : public var::VariantType
|
||||
{
|
||||
|
|
@ -264,38 +284,56 @@ public:
|
|||
};
|
||||
|
||||
//==============================================================================
|
||||
class var::VariantType_Array : public var::VariantType
|
||||
class var::VariantType_Array : public var::VariantType_Object
|
||||
{
|
||||
public:
|
||||
VariantType_Array() noexcept {}
|
||||
static const VariantType_Array instance;
|
||||
|
||||
void cleanUp (ValueUnion& data) const noexcept { delete data.arrayValue; }
|
||||
void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.arrayValue = new Array<var> (*(source.arrayValue)); }
|
||||
|
||||
String toString (const ValueUnion&) const { return "[Array]"; }
|
||||
ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; }
|
||||
bool isArray() const noexcept { return true; }
|
||||
Array<var>* toArray (const ValueUnion& data) const noexcept { return data.arrayValue; }
|
||||
|
||||
Array<var>* toArray (const ValueUnion& data) const noexcept
|
||||
{
|
||||
if (RefCountedArray* a = dynamic_cast<RefCountedArray*> (data.objectValue))
|
||||
return &(a->array);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
|
||||
{
|
||||
const Array<var>* const thisArray = toArray (data);
|
||||
const Array<var>* const otherArray = otherType.toArray (otherData);
|
||||
return otherArray != nullptr && *otherArray == *(data.arrayValue);
|
||||
return thisArray == otherArray || (thisArray != nullptr && otherArray != nullptr && *otherArray == *thisArray);
|
||||
}
|
||||
|
||||
void writeToStream (const ValueUnion& data, OutputStream& output) const
|
||||
{
|
||||
MemoryOutputStream buffer (512);
|
||||
const int numItems = data.arrayValue->size();
|
||||
buffer.writeCompressedInt (numItems);
|
||||
if (const Array<var>* array = toArray (data))
|
||||
{
|
||||
MemoryOutputStream buffer (512);
|
||||
const int numItems = array->size();
|
||||
buffer.writeCompressedInt (numItems);
|
||||
|
||||
for (int i = 0; i < numItems; ++i)
|
||||
data.arrayValue->getReference(i).writeToStream (buffer);
|
||||
for (int i = 0; i < numItems; ++i)
|
||||
array->getReference(i).writeToStream (buffer);
|
||||
|
||||
output.writeCompressedInt (1 + (int) buffer.getDataSize());
|
||||
output.writeByte (varMarker_Array);
|
||||
output << buffer;
|
||||
output.writeCompressedInt (1 + (int) buffer.getDataSize());
|
||||
output.writeByte (varMarker_Array);
|
||||
output << buffer;
|
||||
}
|
||||
}
|
||||
|
||||
struct RefCountedArray : public ReferenceCountedObject
|
||||
{
|
||||
RefCountedArray (const Array<var>& a) : array (a) { incReferenceCount(); }
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
RefCountedArray (Array<var>&& a) : array (static_cast<Array<var>&&> (a)) { incReferenceCount(); }
|
||||
#endif
|
||||
Array<var> array;
|
||||
};
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -351,27 +389,23 @@ public:
|
|||
};
|
||||
|
||||
//==============================================================================
|
||||
const var::VariantType_Void var::VariantType_Void::instance;
|
||||
const var::VariantType_Int var::VariantType_Int::instance;
|
||||
const var::VariantType_Int64 var::VariantType_Int64::instance;
|
||||
const var::VariantType_Bool var::VariantType_Bool::instance;
|
||||
const var::VariantType_Double var::VariantType_Double::instance;
|
||||
const var::VariantType_String var::VariantType_String::instance;
|
||||
const var::VariantType_Object var::VariantType_Object::instance;
|
||||
const var::VariantType_Array var::VariantType_Array::instance;
|
||||
const var::VariantType_Binary var::VariantType_Binary::instance;
|
||||
const var::VariantType_Method var::VariantType_Method::instance;
|
||||
const var::VariantType_Void var::VariantType_Void::instance;
|
||||
const var::VariantType_Undefined var::VariantType_Undefined::instance;
|
||||
const var::VariantType_Int var::VariantType_Int::instance;
|
||||
const var::VariantType_Int64 var::VariantType_Int64::instance;
|
||||
const var::VariantType_Bool var::VariantType_Bool::instance;
|
||||
const var::VariantType_Double var::VariantType_Double::instance;
|
||||
const var::VariantType_String var::VariantType_String::instance;
|
||||
const var::VariantType_Object var::VariantType_Object::instance;
|
||||
const var::VariantType_Array var::VariantType_Array::instance;
|
||||
const var::VariantType_Binary var::VariantType_Binary::instance;
|
||||
const var::VariantType_Method var::VariantType_Method::instance;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
var::var() noexcept : type (&VariantType_Void::instance)
|
||||
{
|
||||
}
|
||||
|
||||
var::~var() noexcept
|
||||
{
|
||||
type->cleanUp (value);
|
||||
}
|
||||
var::var() noexcept : type (&VariantType_Void::instance) {}
|
||||
var::var (const VariantType& t) noexcept : type (&t) {}
|
||||
var::~var() noexcept { type->cleanUp (value); }
|
||||
|
||||
const var var::null;
|
||||
|
||||
|
|
@ -385,8 +419,8 @@ var::var (const int v) noexcept : type (&VariantType_Int::instance) { v
|
|||
var::var (const int64 v) noexcept : type (&VariantType_Int64::instance) { value.int64Value = v; }
|
||||
var::var (const bool v) noexcept : type (&VariantType_Bool::instance) { value.boolValue = v; }
|
||||
var::var (const double v) noexcept : type (&VariantType_Double::instance) { value.doubleValue = v; }
|
||||
var::var (MethodFunction m) noexcept : type (&VariantType_Method::instance) { value.methodValue = m; }
|
||||
var::var (const Array<var>& v) : type (&VariantType_Array::instance) { value.arrayValue = new Array<var> (v); }
|
||||
var::var (NativeFunction m) noexcept : type (&VariantType_Method::instance) { value.methodValue = m; }
|
||||
var::var (const Array<var>& v) : type (&VariantType_Array::instance) { value.objectValue = new VariantType_Array::RefCountedArray(v); }
|
||||
var::var (const String& v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
|
||||
var::var (const char* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
|
||||
var::var (const wchar_t* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
|
||||
|
|
@ -401,9 +435,11 @@ var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::in
|
|||
object->incReferenceCount();
|
||||
}
|
||||
|
||||
var var::undefined() noexcept { return var (VariantType_Undefined::instance); }
|
||||
|
||||
//==============================================================================
|
||||
bool var::isVoid() const noexcept { return type->isVoid(); }
|
||||
bool var::isUndefined() const noexcept { return type->isUndefined(); }
|
||||
bool var::isInt() const noexcept { return type->isInt(); }
|
||||
bool var::isInt64() const noexcept { return type->isInt64(); }
|
||||
bool var::isBool() const noexcept { return type->isBool(); }
|
||||
|
|
@ -443,7 +479,7 @@ var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type =
|
|||
var& var::operator= (const String& v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
|
||||
var& var::operator= (const Array<var>& v) { var v2 (v); swapWith (v2); return *this; }
|
||||
var& var::operator= (ReferenceCountedObject* v) { var v2 (v); swapWith (v2); return *this; }
|
||||
var& var::operator= (MethodFunction v) { var v2 (v); swapWith (v2); return *this; }
|
||||
var& var::operator= (NativeFunction v) { var v2 (v); swapWith (v2); return *this; }
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
var::var (var&& other) noexcept
|
||||
|
|
@ -469,6 +505,11 @@ var::var (MemoryBlock&& v) : type (&VariantType_Binary::instance)
|
|||
value.binaryValue = new MemoryBlock (static_cast<MemoryBlock&&> (v));
|
||||
}
|
||||
|
||||
var::var (Array<var>&& v) : type (&VariantType_Array::instance)
|
||||
{
|
||||
value.objectValue = new VariantType_Array::RefCountedArray (static_cast<Array<var>&&> (v));
|
||||
}
|
||||
|
||||
var& var::operator= (String&& v)
|
||||
{
|
||||
type->cleanUp (value);
|
||||
|
|
@ -508,7 +549,7 @@ var var::operator[] (const Identifier propertyName) const
|
|||
if (DynamicObject* const o = getDynamicObject())
|
||||
return o->getProperty (propertyName);
|
||||
|
||||
return var::null;
|
||||
return var();
|
||||
}
|
||||
|
||||
var var::operator[] (const char* const propertyName) const
|
||||
|
|
@ -524,22 +565,20 @@ var var::getProperty (const Identifier propertyName, const var& defaultReturnVal
|
|||
return defaultReturnValue;
|
||||
}
|
||||
|
||||
var var::invoke (const Identifier method, const var* arguments, int numArguments) const
|
||||
var::NativeFunction var::getNativeFunction() const
|
||||
{
|
||||
if (DynamicObject* const o = getDynamicObject())
|
||||
return o->invokeMethod (method, arguments, numArguments);
|
||||
|
||||
return var::null;
|
||||
return isMethod() ? value.methodValue : nullptr;
|
||||
}
|
||||
|
||||
var var::invokeMethod (DynamicObject* const target, const var* const arguments, const int numArguments) const
|
||||
var var::invoke (Identifier method, const var* arguments, int numArguments) const
|
||||
{
|
||||
jassert (target != nullptr);
|
||||
if (DynamicObject* const o = getDynamicObject())
|
||||
{
|
||||
const var::NativeFunctionArgs args = { *this, arguments, numArguments };
|
||||
return o->invokeMethod (method, args);
|
||||
}
|
||||
|
||||
if (isMethod())
|
||||
return (target->*(value.methodValue)) (arguments, numArguments);
|
||||
|
||||
return var::null;
|
||||
return var();
|
||||
}
|
||||
|
||||
var var::call (const Identifier method) const
|
||||
|
|
@ -609,21 +648,15 @@ var& var::operator[] (int arrayIndex)
|
|||
|
||||
Array<var>* var::convertToArray()
|
||||
{
|
||||
Array<var>* array = getArray();
|
||||
if (Array<var>* array = getArray())
|
||||
return array;
|
||||
|
||||
if (array == nullptr)
|
||||
{
|
||||
const Array<var> tempVar;
|
||||
var v (tempVar);
|
||||
array = v.value.arrayValue;
|
||||
Array<var> tempVar;
|
||||
if (! isVoid())
|
||||
tempVar.add (*this);
|
||||
|
||||
if (! isVoid())
|
||||
array->add (*this);
|
||||
|
||||
swapWith (v);
|
||||
}
|
||||
|
||||
return array;
|
||||
*this = tempVar;
|
||||
return getArray();
|
||||
}
|
||||
|
||||
void var::append (const var& n)
|
||||
|
|
@ -710,5 +743,5 @@ var var::readFromStream (InputStream& input)
|
|||
}
|
||||
}
|
||||
|
||||
return var::null;
|
||||
return var();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,17 @@ class JUCE_API var
|
|||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
typedef const var (DynamicObject::*MethodFunction) (const var* arguments, int numArguments);
|
||||
/** This structure is passed to a NativeFunction callback, and contains invocation
|
||||
details about the function's arguments and context.
|
||||
*/
|
||||
struct NativeFunctionArgs
|
||||
{
|
||||
const var& thisObject;
|
||||
const var* arguments;
|
||||
int numArguments;
|
||||
};
|
||||
|
||||
typedef var (*NativeFunction) (const NativeFunctionArgs&);
|
||||
typedef Identifier identifier;
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -70,7 +80,7 @@ public:
|
|||
var (const String& value);
|
||||
var (const Array<var>& value);
|
||||
var (ReferenceCountedObject* object);
|
||||
var (MethodFunction method) noexcept;
|
||||
var (NativeFunction method) noexcept;
|
||||
var (const void* binaryData, size_t dataSize);
|
||||
var (const MemoryBlock& binaryData);
|
||||
|
||||
|
|
@ -84,18 +94,22 @@ public:
|
|||
var& operator= (const String& value);
|
||||
var& operator= (const Array<var>& value);
|
||||
var& operator= (ReferenceCountedObject* object);
|
||||
var& operator= (MethodFunction method);
|
||||
var& operator= (NativeFunction method);
|
||||
|
||||
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
var (var&& other) noexcept;
|
||||
var (String&& value);
|
||||
var (MemoryBlock&& binaryData);
|
||||
var (Array<var>&& value);
|
||||
var& operator= (var&& other) noexcept;
|
||||
var& operator= (String&& value);
|
||||
#endif
|
||||
|
||||
void swapWith (var& other) noexcept;
|
||||
|
||||
/** Returns a var object that can be used where you need the javascript "undefined" value. */
|
||||
static var undefined() noexcept;
|
||||
|
||||
//==============================================================================
|
||||
operator int() const noexcept;
|
||||
operator int64() const noexcept;
|
||||
|
|
@ -126,6 +140,7 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
bool isVoid() const noexcept;
|
||||
bool isUndefined() const noexcept;
|
||||
bool isInt() const noexcept;
|
||||
bool isInt64() const noexcept;
|
||||
bool isBool() const noexcept;
|
||||
|
|
@ -217,27 +232,29 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/** If this variant is an object, this returns one of its properties. */
|
||||
var operator[] (const Identifier propertyName) const;
|
||||
var operator[] (Identifier propertyName) const;
|
||||
/** If this variant is an object, this returns one of its properties. */
|
||||
var operator[] (const char* propertyName) const;
|
||||
/** If this variant is an object, this returns one of its properties, or a default
|
||||
fallback value if the property is not set. */
|
||||
var getProperty (const Identifier propertyName, const var& defaultReturnValue) const;
|
||||
var getProperty (Identifier propertyName, const var& defaultReturnValue) const;
|
||||
|
||||
/** If this variant is an object, this invokes one of its methods with no arguments. */
|
||||
var call (const Identifier method) const;
|
||||
/** If this variant is an object, this invokes one of its methods with one argument. */
|
||||
var call (const Identifier method, const var& arg1) const;
|
||||
/** If this variant is an object, this invokes one of its methods with 2 arguments. */
|
||||
var call (const Identifier method, const var& arg1, const var& arg2) const;
|
||||
/** If this variant is an object, this invokes one of its methods with 3 arguments. */
|
||||
var call (const Identifier method, const var& arg1, const var& arg2, const var& arg3);
|
||||
/** If this variant is an object, this invokes one of its methods with 4 arguments. */
|
||||
var call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const;
|
||||
/** If this variant is an object, this invokes one of its methods with 5 arguments. */
|
||||
var call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const;
|
||||
/** If this variant is an object, this invokes one of its methods with a list of arguments. */
|
||||
var invoke (const Identifier method, const var* arguments, int numArguments) const;
|
||||
/** Invokes a named method call with no arguments. */
|
||||
var call (Identifier method) const;
|
||||
/** Invokes a named method call with one argument. */
|
||||
var call (Identifier method, const var& arg1) const;
|
||||
/** Invokes a named method call with 2 arguments. */
|
||||
var call (Identifier method, const var& arg1, const var& arg2) const;
|
||||
/** Invokes a named method call with 3 arguments. */
|
||||
var call (Identifier method, const var& arg1, const var& arg2, const var& arg3);
|
||||
/** Invokes a named method call with 4 arguments. */
|
||||
var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const;
|
||||
/** Invokes a named method call with 5 arguments. */
|
||||
var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const;
|
||||
/** Invokes a named method call with a list of arguments. */
|
||||
var invoke (Identifier method, const var* arguments, int numArguments) const;
|
||||
/** If this object is a method, this returns the function pointer. */
|
||||
NativeFunction getNativeFunction() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Writes a binary representation of this value to a stream.
|
||||
|
|
@ -255,17 +272,18 @@ public:
|
|||
|
||||
private:
|
||||
//==============================================================================
|
||||
class VariantType; friend class VariantType;
|
||||
class VariantType_Void; friend class VariantType_Void;
|
||||
class VariantType_Int; friend class VariantType_Int;
|
||||
class VariantType_Int64; friend class VariantType_Int64;
|
||||
class VariantType_Double; friend class VariantType_Double;
|
||||
class VariantType_Bool; friend class VariantType_Bool;
|
||||
class VariantType_String; friend class VariantType_String;
|
||||
class VariantType_Object; friend class VariantType_Object;
|
||||
class VariantType_Array; friend class VariantType_Array;
|
||||
class VariantType_Binary; friend class VariantType_Binary;
|
||||
class VariantType_Method; friend class VariantType_Method;
|
||||
class VariantType; friend class VariantType;
|
||||
class VariantType_Void; friend class VariantType_Void;
|
||||
class VariantType_Undefined; friend class VariantType_Undefined;
|
||||
class VariantType_Int; friend class VariantType_Int;
|
||||
class VariantType_Int64; friend class VariantType_Int64;
|
||||
class VariantType_Double; friend class VariantType_Double;
|
||||
class VariantType_Bool; friend class VariantType_Bool;
|
||||
class VariantType_String; friend class VariantType_String;
|
||||
class VariantType_Object; friend class VariantType_Object;
|
||||
class VariantType_Array; friend class VariantType_Array;
|
||||
class VariantType_Binary; friend class VariantType_Binary;
|
||||
class VariantType_Method; friend class VariantType_Method;
|
||||
|
||||
union ValueUnion
|
||||
{
|
||||
|
|
@ -275,17 +293,15 @@ private:
|
|||
double doubleValue;
|
||||
char stringValue [sizeof (String)];
|
||||
ReferenceCountedObject* objectValue;
|
||||
Array<var>* arrayValue;
|
||||
MemoryBlock* binaryValue;
|
||||
MethodFunction methodValue;
|
||||
NativeFunction methodValue;
|
||||
};
|
||||
|
||||
const VariantType* type;
|
||||
ValueUnion value;
|
||||
|
||||
Array<var>* convertToArray();
|
||||
friend class DynamicObject;
|
||||
var invokeMethod (DynamicObject*, const var*, int) const;
|
||||
var (const VariantType&) noexcept;
|
||||
};
|
||||
|
||||
/** Compares the values of two var objects, using the var::equals() comparison. */
|
||||
|
|
|
|||
|
|
@ -338,6 +338,10 @@ public:
|
|||
{
|
||||
out << "null";
|
||||
}
|
||||
else if (v.isUndefined())
|
||||
{
|
||||
out << "undefined";
|
||||
}
|
||||
else if (v.isBool())
|
||||
{
|
||||
out << (static_cast<bool> (v) ? "true" : "false");
|
||||
|
|
@ -421,29 +425,33 @@ public:
|
|||
const int indentLevel, const bool allOnOneLine)
|
||||
{
|
||||
out << '[';
|
||||
if (! allOnOneLine)
|
||||
out << newLine;
|
||||
|
||||
for (int i = 0; i < array.size(); ++i)
|
||||
if (array.size() > 0)
|
||||
{
|
||||
if (! allOnOneLine)
|
||||
writeSpaces (out, indentLevel + indentSize);
|
||||
|
||||
write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine);
|
||||
|
||||
if (i < array.size() - 1)
|
||||
{
|
||||
if (allOnOneLine)
|
||||
out << ", ";
|
||||
else
|
||||
out << ',' << newLine;
|
||||
}
|
||||
else if (! allOnOneLine)
|
||||
out << newLine;
|
||||
}
|
||||
|
||||
if (! allOnOneLine)
|
||||
writeSpaces (out, indentLevel);
|
||||
for (int i = 0; i < array.size(); ++i)
|
||||
{
|
||||
if (! allOnOneLine)
|
||||
writeSpaces (out, indentLevel + indentSize);
|
||||
|
||||
write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine);
|
||||
|
||||
if (i < array.size() - 1)
|
||||
{
|
||||
if (allOnOneLine)
|
||||
out << ", ";
|
||||
else
|
||||
out << ',' << newLine;
|
||||
}
|
||||
else if (! allOnOneLine)
|
||||
out << newLine;
|
||||
}
|
||||
|
||||
if (! allOnOneLine)
|
||||
writeSpaces (out, indentLevel);
|
||||
}
|
||||
|
||||
out << ']';
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue