public CYUTF8String
{
private:
- const CYJavaRef<jstring> *value_;
+ const CYJavaRef<jstring> &value_;
public:
CYJavaUTF8String(const CYJavaRef<jstring> &value) :
- value_(&value)
+ value_(value)
{
_assert(value);
JNIEnv *jni(value.jni());
data = jni->GetStringUTFChars(value, NULL);
}
- CYJavaUTF8String(const CYJavaRef<jobject> &value) :
- CYJavaUTF8String(CYCastJavaString(value))
- {
- }
+ CYJavaUTF8String(CYJavaRef<jstring> &&) = delete;
~CYJavaUTF8String() {
- if (value_ != NULL) {
- JNIEnv *jni(value_->jni());
- jni->ReleaseStringUTFChars(*value_, data);
- }
+ JNIEnv *jni(value_.jni());
+ jni->ReleaseStringUTFChars(value_, data);
}
CYJavaUTF8String(const CYJavaUTF8String &) = delete;
-
- CYJavaUTF8String(CYJavaUTF8String &&rhs) :
- value_(rhs.value_)
- {
- rhs.value_ = NULL;
- }
};
CYJavaUTF8String CYCastUTF8String(const CYJavaRef<jstring> &value) {
- return CYJavaUTF8String(value);
+ return {value};
}
JSStringRef CYCopyJSString(const CYJavaRef<jstring> &value) {
}
virtual const char *PoolCString(CYPool &pool) const {
- return CYPoolCString(pool, CYJavaUTF8String(value_.cast<jobject>()));
+ auto string(CYCastJavaString(value_.cast<jobject>()));
+ return CYPoolCString(pool, CYJavaUTF8String(string));
}
virtual JSValueRef CastJSValue(JSContextRef context, const char *name) const;
{
}
- CYJavaSignature(unsigned count) :
- shorty_(count)
- {
- }
-
+ // XXX: the shorty doesn't store enough information
bool operator <(const CYJavaSignature &rhs) const {
- return shorty_.size() < rhs.shorty_.size();
+ return shorty_ < rhs.shorty_;
}
};
-typedef std::multiset<CYJavaSignature> CYJavaOverload;
+typedef std::set<CYJavaSignature> CYJavaOverload;
+typedef std::map<unsigned, CYJavaOverload> CYJavaOverloads;
struct CYJavaMethod :
CYRoot
{
- CYJavaOverload overload_;
-
- CYJavaMethod(const CYJavaOverload &overload) :
- overload_(overload)
+ CYUTF8String type_;
+ CYUTF8String name_;
+ CYJavaOverloads overloads_;
+
+ CYJavaMethod(CYUTF8String type, CYUTF8String name, const CYJavaOverloads &overloads) :
+ type_(CYPoolUTF8String(*pool_, type)),
+ name_(CYPoolUTF8String(*pool_, name)),
+ overloads_(overloads)
{
}
};
-struct CYJavaStaticMethod :
- CYRoot
+struct CYJavaInstanceMethod :
+ CYJavaMethod
{
- CYJavaOverload overload_;
+ using CYJavaMethod::CYJavaMethod;
+};
- CYJavaStaticMethod(const CYJavaOverload &overload) :
- overload_(overload)
- {
- }
+struct CYJavaStaticMethod :
+ CYJavaMethod
+{
+ using CYJavaMethod::CYJavaMethod;
};
struct CYJavaClass :
CYJavaFieldMap static_;
CYJavaFieldMap instance_;
- CYJavaOverload overload_;
+ CYJavaOverloads overloads_;
CYJavaClass(const CYJavaRef<jclass> &value, bool interface) :
value_(value),
auto Class$(jni.FindClass("java/lang/Class"));
auto Class$getName(jni.GetMethodID(Class$, "getName", "()Ljava/lang/String;"));
- CYJSString name(jni.CallObjectMethod<jstring>(value, Class$getName));
+ auto string(jni.CallObjectMethod<jstring>(value, Class$getName));
+ CYJavaUTF8String utf8(string);
+ CYJSString name(utf8);
+
JSValueRef cached(CYGetProperty(context, cy, name));
if (!JSValueIsUndefined(context, cached))
return CYCastJSObject(context, cached);
auto modifiers(jni.CallIntMethod(field, Field$getModifiers));
auto instance(!jni.CallStaticBooleanMethod(Modifier$, Modifier$isStatic, modifiers));
auto &map(instance ? table->instance_ : table->static_);
- CYJavaUTF8String name(jni.CallObjectMethod<jstring>(field, Field$getName));
+ auto string(jni.CallObjectMethod<jstring>(field, Field$getName));
+ CYJavaUTF8String name(string);
auto id(jni.FromReflectedField(field));
auto type(jni.CallObjectMethod<jclass>(field, Field$getType));
map.insert(std::make_pair(std::string(name), CYJavaField{id, CYJavaGetPrimitive(context, type, Class$getName)}));
auto parameters(jni.CallObjectMethod<jobjectArray>(constructor, Constructor$getParameterTypes));
CYJavaShorty shorty(CYJavaGetShorty(context, parameters, Class$getName));
auto id(jni.FromReflectedMethod(constructor));
- table->overload_.insert(CYJavaSignature(constructor, id, CYJavaPrimitiveObject, shorty));
+ table->overloads_[shorty.size()].insert(CYJavaSignature(constructor, id, CYJavaPrimitiveObject, shorty));
}
- auto methods(jni.CallObjectMethod<jobjectArray>(value, Class$getDeclaredMethods));
+ std::map<std::pair<bool, std::string>, CYJavaOverloads> entries;
- std::map<std::pair<bool, std::string>, CYJavaOverload> entries;
+ bool base(false);
+ for (CYJavaLocal<jclass> prototype(value); prototype; prototype = jni.GetSuperclass(prototype)) {
+ auto methods(jni.CallObjectMethod<jobjectArray>(prototype, Class$getDeclaredMethods));
- for (jsize i(0), e(jni.GetArrayLength(methods)); i != e; ++i) {
- auto method(jni.GetObjectArrayElement<jobject>(methods, i));
- auto modifiers(jni.CallIntMethod(method, Method$getModifiers));
- auto instance(!jni.CallStaticBooleanMethod(Modifier$, Modifier$isStatic, modifiers));
- CYJavaUTF8String name(jni.CallObjectMethod<jstring>(method, Method$getName));
- auto parameters(jni.CallObjectMethod<jobjectArray>(method, Method$getParameterTypes));
- CYJavaShorty shorty(CYJavaGetShorty(context, parameters, Class$getName));
- auto type(jni.CallObjectMethod<jclass>(method, Method$getReturnType));
- auto primitive(CYJavaGetPrimitive(context, type, Class$getName));
- auto id(jni.FromReflectedMethod(method));
- entries[std::make_pair(instance, std::string(name))].insert(CYJavaSignature(method, id, primitive, shorty));
+ for (jsize i(0), e(jni.GetArrayLength(methods)); i != e; ++i) {
+ auto method(jni.GetObjectArrayElement<jobject>(methods, i));
+ auto modifiers(jni.CallIntMethod(method, Method$getModifiers));
+ auto instance(!jni.CallStaticBooleanMethod(Modifier$, Modifier$isStatic, modifiers));
+ auto string(jni.CallObjectMethod<jstring>(method, Method$getName));
+ CYJavaUTF8String name(string);
+
+ auto parameters(jni.CallObjectMethod<jobjectArray>(method, Method$getParameterTypes));
+ CYJavaShorty shorty(CYJavaGetShorty(context, parameters, Class$getName));
+
+ CYJavaOverload *overload;
+ if (!base)
+ overload = &entries[std::make_pair(instance, std::string(name))][shorty.size()];
+ else {
+ auto entry(entries.find(std::make_pair(instance, std::string(name))));
+ if (entry == entries.end())
+ continue;
+ overload = &entry->second[shorty.size()];
+ }
+
+ auto type(jni.CallObjectMethod<jclass>(method, Method$getReturnType));
+ auto primitive(CYJavaGetPrimitive(context, type, Class$getName));
+ auto id(jni.FromReflectedMethod(method));
+ overload->insert(CYJavaSignature(method, id, primitive, shorty));
+ }
+
+ base = true;
}
for (const auto &entry : entries) {
bool instance(entry.first.first);
- CYJSString name(entry.first.second);
+ CYJSString method(entry.first.second);
auto &overload(entry.second);
if (instance)
- CYSetProperty(context, prototype, name, CYPrivate<CYJavaMethod>::Make(context, overload), kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete);
+ CYSetProperty(context, prototype, method, CYPrivate<CYJavaInstanceMethod>::Make(context, utf8, entry.first.second.c_str(), overload), kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete);
else
- CYSetProperty(context, constructor, name, CYPrivate<CYJavaStaticMethod>::Make(context, overload), kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete);
+ CYSetProperty(context, constructor, method, CYPrivate<CYJavaStaticMethod>::Make(context, utf8, entry.first.second.c_str(), overload), kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete);
}
}
return true;
}
-static JSValueRef JavaMethod_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
- auto internal(CYPrivate<CYJavaMethod>::Get(context, object));
+static JSValueRef JavaInstanceMethod_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+ auto internal(CYPrivate<CYJavaInstanceMethod>::Get(context, object));
CYJavaObject *self(CYGetJavaObject(context, _this));
_assert(self != NULL);
CYJavaEnv jni(self->value_);
- CYJavaSignature bound(count);
- for (auto overload(internal->overload_.lower_bound(bound)), e(internal->overload_.upper_bound(bound)); overload != e; ++overload) {
+ auto overload(internal->overloads_.find(count));
+ if (overload != internal->overloads_.end())
+ for (auto signature(overload->second.begin()); signature != overload->second.end(); ++signature) {
CYJavaFrame frame(jni, count + 16);
jvalue array[count];
- if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array))
+ if (!CYCastJavaArguments(frame, signature->shorty_, context, arguments, array))
continue;
jvalue *values(array);
- switch (overload->primitive_) {
+ switch (signature->primitive_) {
case CYJavaPrimitiveObject:
- return CYCastJSValue(context, jni.CallObjectMethodA<jobject>(self->value_, overload->method_, values));
+ return CYCastJSValue(context, jni.CallObjectMethodA<jobject>(self->value_, signature->method_, values));
case CYJavaPrimitiveVoid:
- jni.CallVoidMethodA(self->value_, overload->method_, values);
+ jni.CallVoidMethodA(self->value_, signature->method_, values);
return CYJSUndefined(context);
#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
case CYJavaPrimitive ## Type: \
- return CYJavaCastJSValue(context, jni.Call ## Typ ## MethodA(self->value_, overload->method_, values));
+ return CYJavaCastJSValue(context, jni.Call ## Typ ## MethodA(self->value_, signature->method_, values));
CYJavaForEachPrimitive
#undef CYJavaForEachPrimitive_
default: _assert(false);
CYJavaClass *table(CYGetJavaTable(context, _this));
CYJavaEnv jni(table->value_);
- CYJavaSignature bound(count);
- for (auto overload(internal->overload_.lower_bound(bound)), e(internal->overload_.upper_bound(bound)); overload != e; ++overload) {
+ auto overload(internal->overloads_.find(count));
+ if (overload != internal->overloads_.end())
+ for (auto signature(overload->second.begin()); signature != overload->second.end(); ++signature) {
CYJavaFrame frame(jni, count + 16);
jvalue array[count];
- if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array))
+ if (!CYCastJavaArguments(frame, signature->shorty_, context, arguments, array))
continue;
jvalue *values(array);
- switch (overload->primitive_) {
+ switch (signature->primitive_) {
case CYJavaPrimitiveObject:
- return CYCastJSValue(context, jni.CallStaticObjectMethodA<jobject>(table->value_, overload->method_, values));
+ return CYCastJSValue(context, jni.CallStaticObjectMethodA<jobject>(table->value_, signature->method_, values));
case CYJavaPrimitiveVoid:
- jni.CallStaticVoidMethodA(table->value_, overload->method_, values);
+ jni.CallStaticVoidMethodA(table->value_, signature->method_, values);
return CYJSUndefined(context);
#define CYJavaForEachPrimitive_(T, t, Typ, Type, type) \
case CYJavaPrimitive ## Type: \
- return CYJavaCastJSValue(context, jni.CallStatic ## Typ ## MethodA(table->value_, overload->method_, values));
+ return CYJavaCastJSValue(context, jni.CallStatic ## Typ ## MethodA(table->value_, signature->method_, values));
CYJavaForEachPrimitive
#undef CYJavaForEachPrimitive_
default: _assert(false);
return CYCastJSObject(context, jni.CallObjectMethod<jobject>(Cycript$, Cycript$Make, _class, CYCastJavaObject(jni, context, CYCastJSObject(context, arguments[0])).get()));
}
- CYJavaSignature bound(count);
- for (auto overload(table->overload_.lower_bound(bound)), e(table->overload_.upper_bound(bound)); overload != e; ++overload) {
+ auto overload(table->overloads_.find(count));
+ if (overload != table->overloads_.end())
+ for (auto signature(overload->second.begin()); signature != overload->second.end(); ++signature) {
CYJavaFrame frame(jni, count + 16);
jvalue array[count];
- if (!CYCastJavaArguments(frame, overload->shorty_, context, arguments, array))
+ if (!CYCastJavaArguments(frame, signature->shorty_, context, arguments, array))
continue;
jvalue *values(array);
- auto object(jni.NewObjectA(_class, overload->method_, values));
+ auto object(jni.NewObjectA(_class, signature->method_, values));
return CYCastJSObject(context, object);
}
CYThrow("invalid constructor call");
-} CYCatch(NULL) }
+} CYCatchObject() }
static bool JavaStaticInterior_hasProperty(JSContextRef context, JSObjectRef object, JSStringRef property) {
auto internal(CYPrivate<CYJavaStaticInterior>::Get(context, object));
} CYCatch(NULL) }
static JSValueRef JavaMethod_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
+ auto internal(CYPrivate<CYJavaMethod>::Get(context, _this));
std::ostringstream cyon;
- return CYCastJSValue(context, CYJSString(cyon.str()));
-} CYCatch(NULL) }
-
-static JSValueRef JavaStaticMethod_callAsFunction_toCYON(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
- std::ostringstream cyon;
+ if (false)
+ cyon << internal->type_ << "." << internal->name_;
+ else {
+ bool comma(false);
+ for (auto overload(internal->overloads_.begin()); overload != internal->overloads_.end(); ++overload)
+ for (auto signature(overload->second.begin()); signature != overload->second.end(); ++signature) {
+ if (comma)
+ cyon << std::endl;
+ else
+ comma = true;
+ auto string(CYCastJavaString(signature->reflected_));
+ cyon << CYJavaUTF8String(string);
+ }
+ }
return CYCastJSValue(context, CYJSString(cyon.str()));
} CYCatch(NULL) }
{NULL, NULL, NULL, 0}
};
-static JSStaticFunction JavaMethod_staticFunctions[2] = {
+static JSStaticFunction JavaInstanceMethod_staticFunctions[2] = {
{"toCYON", &JavaMethod_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL, 0}
};
static JSStaticFunction JavaStaticMethod_staticFunctions[2] = {
- {"toCYON", &JavaStaticMethod_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
+ {"toCYON", &JavaMethod_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL, 0}
};
definition = kJSClassDefinitionEmpty;
definition.className = "JavaMethod";
- definition.staticFunctions = JavaMethod_staticFunctions;
- definition.callAsFunction = &JavaMethod_callAsFunction;
definition.finalize = &CYFinalize;
CYPrivate<CYJavaMethod>::Class_ = JSClassCreate(&definition);
+ definition = kJSClassDefinitionEmpty;
+ definition.className = "JavaInstanceMethod";
+ definition.parentClass = CYPrivate<CYJavaMethod>::Class_;
+ definition.staticFunctions = JavaInstanceMethod_staticFunctions;
+ definition.callAsFunction = &JavaInstanceMethod_callAsFunction;
+ CYPrivate<CYJavaInstanceMethod>::Class_ = JSClassCreate(&definition);
+
definition = kJSClassDefinitionEmpty;
definition.className = "JavaStaticMethod";
+ definition.parentClass = CYPrivate<CYJavaMethod>::Class_;
definition.staticFunctions = JavaStaticMethod_staticFunctions;
definition.callAsFunction = &JavaStaticMethod_callAsFunction;
- definition.finalize = &CYFinalize;
CYPrivate<CYJavaStaticMethod>::Class_ = JSClassCreate(&definition);
definition = kJSClassDefinitionEmpty;